From 5ead147812835d97c4bb77b7eecfbdda635f680c Mon Sep 17 00:00:00 2001 From: Bones Date: Tue, 4 Jun 2024 01:14:55 -0400 Subject: [PATCH] rtsp patchset 9 --- patches/protonprep-valve-staging.sh | 72 +- ...ng-support-for-IMFMediaSession-Start.patch | 128 +++ ...reate_media_session_with_source_sink.patch | 143 ++++ ...-mf-tests-Test-IMFMediaSession-Start.patch | 784 ++++++++++++++++++ ...plement-IMFMediaEngineEx-SetCurrentT.patch | 109 +++ ...sts-Test-IMFMediaEngineEx-SetCurrent.patch | 243 ++++++ .../0006-AVPro-Video-seeking-support.patch | 22 + ...leaking-samples-in-transform_node_d.patch} | 4 +- ...xes.patch => 0008-Memory-leak-fixes.patch} | 4 +- ...nect-autoplug-continue-and-deep-ele.patch} | 8 +- ...not-create-a-read-thread-for-uridec.patch} | 4 +- ...eamer-Ignore-an-assert-in-wg_parser.patch} | 6 +- ...Fixate-caps-in-autoplug_continue_cb.patch} | 6 +- ...e-wg_parser-report-the-exact-suppor.patch} | 6 +- ...-more-RTSP-based-URI-schemes-to-GSt.patch} | 4 +- ...xate-caps-in-the-pad-added-callback.patch} | 6 +- ...k-wg_parser-container-bin-as-stream.patch} | 8 +- ...-a-clock-for-the-wg_parser-pipeline.patch} | 8 +- ...-base-time-on-wg_parser-bin-while-c.patch} | 12 +- ...-pipeline-into-PLAYING-state-before.patch} | 8 +- ...-t-only-accept-segment-events-when-.patch} | 6 +- ...vert-buffer-presentation-timestamps.patch} | 6 +- ...Adjust-buffer-timestamps-after-seek.patch} | 6 +- ...rder-parser-initialization-code-a-b.patch} | 16 +- ...away-with-the-per-stream-condvars-a.patch} | 10 +- ...-pthread_cond_broadcast-instead-of-.patch} | 8 +- ...not-fail-caps-negotiation-when-ther.patch} | 10 +- ...egstreamer-Do-not-seek-live-sources.patch} | 10 +- ...streamer-Implement-buffering-events.patch} | 14 +- ...quests-for-unused-space-of-sample-q.patch} | 4 +- ...d-a-queue-of-buffers-to-wg_parser-to.patch | 196 +++++ ...x-race-between-wg_parser_stream_disa.patch | 27 + ...r-Add-a-resampler-to-wg_parser-for-.patch} | 8 +- ...r-Add-a-videoscale-element-to-wg_pa.patch} | 10 +- ...e-Do-not-send-MF_MEDIA_ENGINE_EVENT.patch} | 8 +- ...35-Marker-commit-do-not-put-into-MR.patch} | 4 +- ...BUG-winegstreamer-GST_LOG-GST_DEBUG.patch} | 42 +- ...t-dlp.exe-redirection-and-cmdline-m.patch} | 4 +- ...d-timers-for-the-original-time-inst.patch} | 4 +- ...ng-samples-only-at-the-PTS-of-the-f.patch} | 4 +- ...l-instead-of-syscall-for-QueryPerfo.patch} | 4 +- wine | 2 +- 42 files changed, 1824 insertions(+), 164 deletions(-) create mode 100644 patches/wine-gst/0001-mf-Add-seeking-support-for-IMFMediaSession-Start.patch create mode 100644 patches/wine-gst/0002-mf-tests-Add-a-create_media_session_with_source_sink.patch create mode 100644 patches/wine-gst/0003-mf-tests-Test-IMFMediaSession-Start.patch create mode 100644 patches/wine-gst/0004-mfmediaengine-Implement-IMFMediaEngineEx-SetCurrentT.patch create mode 100644 patches/wine-gst/0005-mfmediaengine-tests-Test-IMFMediaEngineEx-SetCurrent.patch create mode 100644 patches/wine-gst/0006-AVPro-Video-seeking-support.patch rename patches/wine-gst/{0001-mf-session-Avoid-leaking-samples-in-transform_node_d.patch => 0007-mf-session-Avoid-leaking-samples-in-transform_node_d.patch} (88%) rename patches/wine-gst/{0002-Memory-leak-fixes.patch => 0008-Memory-leak-fixes.patch} (77%) rename patches/wine-gst/{0003-winegstreamer-Connect-autoplug-continue-and-deep-ele.patch => 0009-winegstreamer-Connect-autoplug-continue-and-deep-ele.patch} (83%) rename patches/wine-gst/{0004-winegstreamer-Do-not-create-a-read-thread-for-uridec.patch => 0010-winegstreamer-Do-not-create-a-read-thread-for-uridec.patch} (91%) rename patches/wine-gst/{0005-winegstreamer-Ignore-an-assert-in-wg_parser.patch => 0011-winegstreamer-Ignore-an-assert-in-wg_parser.patch} (87%) rename patches/wine-gst/{0006-winegstreamer-Fixate-caps-in-autoplug_continue_cb.patch => 0012-winegstreamer-Fixate-caps-in-autoplug_continue_cb.patch} (81%) rename patches/wine-gst/{0007-winegstreamer-Make-wg_parser-report-the-exact-suppor.patch => 0013-winegstreamer-Make-wg_parser-report-the-exact-suppor.patch} (94%) rename patches/wine-gst/{0008-winegstreamer-Add-more-RTSP-based-URI-schemes-to-GSt.patch => 0014-winegstreamer-Add-more-RTSP-based-URI-schemes-to-GSt.patch} (94%) rename patches/wine-gst/{0009-winegstreamer-Fixate-caps-in-the-pad-added-callback.patch => 0015-winegstreamer-Fixate-caps-in-the-pad-added-callback.patch} (88%) rename patches/wine-gst/{0010-winegstreamer-Mark-wg_parser-container-bin-as-stream.patch => 0016-winegstreamer-Mark-wg_parser-container-bin-as-stream.patch} (74%) rename patches/wine-gst/{0011-winegstreamer-Set-a-clock-for-the-wg_parser-pipeline.patch => 0017-winegstreamer-Set-a-clock-for-the-wg_parser-pipeline.patch} (78%) rename patches/wine-gst/{0012-winegstreamer-Set-base-time-on-wg_parser-bin-while-c.patch => 0018-winegstreamer-Set-base-time-on-wg_parser-bin-while-c.patch} (78%) rename patches/wine-gst/{0013-winegstreamer-Put-pipeline-into-PLAYING-state-before.patch => 0019-winegstreamer-Put-pipeline-into-PLAYING-state-before.patch} (80%) rename patches/wine-gst/{0014-winegstreamer-Don-t-only-accept-segment-events-when-.patch => 0020-winegstreamer-Don-t-only-accept-segment-events-when-.patch} (91%) rename patches/wine-gst/{0015-winegstreamer-Convert-buffer-presentation-timestamps.patch => 0021-winegstreamer-Convert-buffer-presentation-timestamps.patch} (94%) rename patches/wine-gst/{0016-winegstreamer-Adjust-buffer-timestamps-after-seek.patch => 0022-winegstreamer-Adjust-buffer-timestamps-after-seek.patch} (92%) rename patches/wine-gst/{0017-winegstreamer-Reorder-parser-initialization-code-a-b.patch => 0023-winegstreamer-Reorder-parser-initialization-code-a-b.patch} (87%) rename patches/wine-gst/{0018-winegstreamer-Do-away-with-the-per-stream-condvars-a.patch => 0024-winegstreamer-Do-away-with-the-per-stream-condvars-a.patch} (94%) rename patches/wine-gst/{0019-winegstreamer-Use-pthread_cond_broadcast-instead-of-.patch => 0025-winegstreamer-Use-pthread_cond_broadcast-instead-of-.patch} (92%) rename patches/wine-gst/{0020-winegstreamer-Do-not-fail-caps-negotiation-when-ther.patch => 0026-winegstreamer-Do-not-fail-caps-negotiation-when-ther.patch} (96%) rename patches/wine-gst/{0021-winegstreamer-Do-not-seek-live-sources.patch => 0027-winegstreamer-Do-not-seek-live-sources.patch} (91%) rename patches/wine-gst/{0022-winegstreamer-Implement-buffering-events.patch => 0028-winegstreamer-Implement-buffering-events.patch} (95%) rename patches/wine-gst/{0032-mf-Send-sample-requests-for-unused-space-of-sample-q.patch => 0029-mf-Send-sample-requests-for-unused-space-of-sample-q.patch} (96%) create mode 100644 patches/wine-gst/0030-winegstreamer-Add-a-queue-of-buffers-to-wg_parser-to.patch create mode 100644 patches/wine-gst/0031-winegstreamer-Fix-race-between-wg_parser_stream_disa.patch rename patches/wine-gst/{0023-HACK-winegstreamer-Add-a-resampler-to-wg_parser-for-.patch => 0032-HACK-winegstreamer-Add-a-resampler-to-wg_parser-for-.patch} (80%) rename patches/wine-gst/{0024-HACK-winegstreamer-Add-a-videoscale-element-to-wg_pa.patch => 0033-HACK-winegstreamer-Add-a-videoscale-element-to-wg_pa.patch} (83%) rename patches/wine-gst/{0025-HACK-mfmediaengine-Do-not-send-MF_MEDIA_ENGINE_EVENT.patch => 0034-HACK-mfmediaengine-Do-not-send-MF_MEDIA_ENGINE_EVENT.patch} (89%) rename patches/wine-gst/{0026-Marker-commit-do-not-put-into-MR.patch => 0035-Marker-commit-do-not-put-into-MR.patch} (72%) rename patches/wine-gst/{0027-DEBUG-winegstreamer-GST_LOG-GST_DEBUG.patch => 0036-DEBUG-winegstreamer-GST_LOG-GST_DEBUG.patch} (80%) rename patches/wine-gst/{0028-HACK-kernelbase-yt-dlp.exe-redirection-and-cmdline-m.patch => 0037-HACK-kernelbase-yt-dlp.exe-redirection-and-cmdline-m.patch} (95%) rename patches/wine-gst/{0029-mf-Schedule-stored-timers-for-the-original-time-inst.patch => 0038-mf-Schedule-stored-timers-for-the-original-time-inst.patch} (95%) rename patches/wine-gst/{0030-mf-Start-forwarding-samples-only-at-the-PTS-of-the-f.patch => 0039-mf-Start-forwarding-samples-only-at-the-PTS-of-the-f.patch} (98%) rename patches/wine-gst/{0031-ntdll-Use-unixcall-instead-of-syscall-for-QueryPerfo.patch => 0040-ntdll-Use-unixcall-instead-of-syscall-for-QueryPerfo.patch} (96%) diff --git a/patches/protonprep-valve-staging.sh b/patches/protonprep-valve-staging.sh index 1c0594646..3b64e4fa7 100755 --- a/patches/protonprep-valve-staging.sh +++ b/patches/protonprep-valve-staging.sh @@ -299,38 +299,46 @@ patch -Np1 < ../patches/wine-hotfixes/pending/add-envvar-to-gate-media-converter.patch echo "WINE: RTSP patch" - patch -Np1 < ../patches/wine-gst/0001-mf-session-Avoid-leaking-samples-in-transform_node_d.patch - patch -Np1 < ../patches/wine-gst/0002-Memory-leak-fixes.patch - patch -Np1 < ../patches/wine-gst/0003-winegstreamer-Connect-autoplug-continue-and-deep-ele.patch - patch -Np1 < ../patches/wine-gst/0004-winegstreamer-Do-not-create-a-read-thread-for-uridec.patch - patch -Np1 < ../patches/wine-gst/0005-winegstreamer-Ignore-an-assert-in-wg_parser.patch - patch -Np1 < ../patches/wine-gst/0006-winegstreamer-Fixate-caps-in-autoplug_continue_cb.patch - patch -Np1 < ../patches/wine-gst/0007-winegstreamer-Make-wg_parser-report-the-exact-suppor.patch - patch -Np1 < ../patches/wine-gst/0008-winegstreamer-Add-more-RTSP-based-URI-schemes-to-GSt.patch - patch -Np1 < ../patches/wine-gst/0009-winegstreamer-Fixate-caps-in-the-pad-added-callback.patch - patch -Np1 < ../patches/wine-gst/0010-winegstreamer-Mark-wg_parser-container-bin-as-stream.patch - patch -Np1 < ../patches/wine-gst/0011-winegstreamer-Set-a-clock-for-the-wg_parser-pipeline.patch - patch -Np1 < ../patches/wine-gst/0012-winegstreamer-Set-base-time-on-wg_parser-bin-while-c.patch - patch -Np1 < ../patches/wine-gst/0013-winegstreamer-Put-pipeline-into-PLAYING-state-before.patch - patch -Np1 < ../patches/wine-gst/0014-winegstreamer-Don-t-only-accept-segment-events-when-.patch - patch -Np1 < ../patches/wine-gst/0015-winegstreamer-Convert-buffer-presentation-timestamps.patch - patch -Np1 < ../patches/wine-gst/0016-winegstreamer-Adjust-buffer-timestamps-after-seek.patch - patch -Np1 < ../patches/wine-gst/0017-winegstreamer-Reorder-parser-initialization-code-a-b.patch - patch -Np1 < ../patches/wine-gst/0018-winegstreamer-Do-away-with-the-per-stream-condvars-a.patch - patch -Np1 < ../patches/wine-gst/0019-winegstreamer-Use-pthread_cond_broadcast-instead-of-.patch - patch -Np1 < ../patches/wine-gst/0020-winegstreamer-Do-not-fail-caps-negotiation-when-ther.patch - patch -Np1 < ../patches/wine-gst/0021-winegstreamer-Do-not-seek-live-sources.patch - patch -Np1 < ../patches/wine-gst/0022-winegstreamer-Implement-buffering-events.patch - patch -Np1 < ../patches/wine-gst/0023-HACK-winegstreamer-Add-a-resampler-to-wg_parser-for-.patch - patch -Np1 < ../patches/wine-gst/0024-HACK-winegstreamer-Add-a-videoscale-element-to-wg_pa.patch - patch -Np1 < ../patches/wine-gst/0025-HACK-mfmediaengine-Do-not-send-MF_MEDIA_ENGINE_EVENT.patch - patch -Np1 < ../patches/wine-gst/0026-Marker-commit-do-not-put-into-MR.patch - patch -Np1 < ../patches/wine-gst/0027-DEBUG-winegstreamer-GST_LOG-GST_DEBUG.patch - patch -Np1 < ../patches/wine-gst/0028-HACK-kernelbase-yt-dlp.exe-redirection-and-cmdline-m.patch - patch -Np1 < ../patches/wine-gst/0029-mf-Schedule-stored-timers-for-the-original-time-inst.patch - patch -Np1 < ../patches/wine-gst/0030-mf-Start-forwarding-samples-only-at-the-PTS-of-the-f.patch - patch -Np1 < ../patches/wine-gst/0031-ntdll-Use-unixcall-instead-of-syscall-for-QueryPerfo.patch - patch -Np1 < ../patches/wine-gst/0032-mf-Send-sample-requests-for-unused-space-of-sample-q.patch + patch -Np1 < ../patches/wine-gst/0001-mf-Add-seeking-support-for-IMFMediaSession-Start.patch + patch -Np1 < ../patches/wine-gst/0002-mf-tests-Add-a-create_media_session_with_source_sink.patch + patch -Np1 < ../patches/wine-gst/0003-mf-tests-Test-IMFMediaSession-Start.patch + patch -Np1 < ../patches/wine-gst/0004-mfmediaengine-Implement-IMFMediaEngineEx-SetCurrentT.patch + patch -Np1 < ../patches/wine-gst/0005-mfmediaengine-tests-Test-IMFMediaEngineEx-SetCurrent.patch + patch -Np1 < ../patches/wine-gst/0006-AVPro-Video-seeking-support.patch + patch -Np1 < ../patches/wine-gst/0007-mf-session-Avoid-leaking-samples-in-transform_node_d.patch + patch -Np1 < ../patches/wine-gst/0008-Memory-leak-fixes.patch + patch -Np1 < ../patches/wine-gst/0009-winegstreamer-Connect-autoplug-continue-and-deep-ele.patch + patch -Np1 < ../patches/wine-gst/0010-winegstreamer-Do-not-create-a-read-thread-for-uridec.patch + patch -Np1 < ../patches/wine-gst/0011-winegstreamer-Ignore-an-assert-in-wg_parser.patch + patch -Np1 < ../patches/wine-gst/0012-winegstreamer-Fixate-caps-in-autoplug_continue_cb.patch + patch -Np1 < ../patches/wine-gst/0013-winegstreamer-Make-wg_parser-report-the-exact-suppor.patch + patch -Np1 < ../patches/wine-gst/0014-winegstreamer-Add-more-RTSP-based-URI-schemes-to-GSt.patch + patch -Np1 < ../patches/wine-gst/0015-winegstreamer-Fixate-caps-in-the-pad-added-callback.patch + patch -Np1 < ../patches/wine-gst/0016-winegstreamer-Mark-wg_parser-container-bin-as-stream.patch + patch -Np1 < ../patches/wine-gst/0017-winegstreamer-Set-a-clock-for-the-wg_parser-pipeline.patch + patch -Np1 < ../patches/wine-gst/0018-winegstreamer-Set-base-time-on-wg_parser-bin-while-c.patch + patch -Np1 < ../patches/wine-gst/0019-winegstreamer-Put-pipeline-into-PLAYING-state-before.patch + patch -Np1 < ../patches/wine-gst/0020-winegstreamer-Don-t-only-accept-segment-events-when-.patch + patch -Np1 < ../patches/wine-gst/0021-winegstreamer-Convert-buffer-presentation-timestamps.patch + patch -Np1 < ../patches/wine-gst/0022-winegstreamer-Adjust-buffer-timestamps-after-seek.patch + patch -Np1 < ../patches/wine-gst/0023-winegstreamer-Reorder-parser-initialization-code-a-b.patch + patch -Np1 < ../patches/wine-gst/0024-winegstreamer-Do-away-with-the-per-stream-condvars-a.patch + patch -Np1 < ../patches/wine-gst/0025-winegstreamer-Use-pthread_cond_broadcast-instead-of-.patch + patch -Np1 < ../patches/wine-gst/0026-winegstreamer-Do-not-fail-caps-negotiation-when-ther.patch + patch -Np1 < ../patches/wine-gst/0027-winegstreamer-Do-not-seek-live-sources.patch + patch -Np1 < ../patches/wine-gst/0028-winegstreamer-Implement-buffering-events.patch + patch -Np1 < ../patches/wine-gst/0029-mf-Send-sample-requests-for-unused-space-of-sample-q.patch + patch -Np1 < ../patches/wine-gst/0030-winegstreamer-Add-a-queue-of-buffers-to-wg_parser-to.patch + patch -Np1 < ../patches/wine-gst/0031-winegstreamer-Fix-race-between-wg_parser_stream_disa.patch + patch -Np1 < ../patches/wine-gst/0032-HACK-winegstreamer-Add-a-resampler-to-wg_parser-for-.patch + patch -Np1 < ../patches/wine-gst/0033-HACK-winegstreamer-Add-a-videoscale-element-to-wg_pa.patch + patch -Np1 < ../patches/wine-gst/0034-HACK-mfmediaengine-Do-not-send-MF_MEDIA_ENGINE_EVENT.patch + patch -Np1 < ../patches/wine-gst/0035-Marker-commit-do-not-put-into-MR.patch + patch -Np1 < ../patches/wine-gst/0036-DEBUG-winegstreamer-GST_LOG-GST_DEBUG.patch + patch -Np1 < ../patches/wine-gst/0037-HACK-kernelbase-yt-dlp.exe-redirection-and-cmdline-m.patch + patch -Np1 < ../patches/wine-gst/0038-mf-Schedule-stored-timers-for-the-original-time-inst.patch + patch -Np1 < ../patches/wine-gst/0039-mf-Start-forwarding-samples-only-at-the-PTS-of-the-f.patch + patch -Np1 < ../patches/wine-gst/0040-ntdll-Use-unixcall-instead-of-syscall-for-QueryPerfo.patch #echo "WINE: -Nvidia Reflex- Support VK_NV_low_latency2" #patch -Np1 < ../patches/proton/83-nv_low_latency_wine.patch diff --git a/patches/wine-gst/0001-mf-Add-seeking-support-for-IMFMediaSession-Start.patch b/patches/wine-gst/0001-mf-Add-seeking-support-for-IMFMediaSession-Start.patch new file mode 100644 index 000000000..3aba157ec --- /dev/null +++ b/patches/wine-gst/0001-mf-Add-seeking-support-for-IMFMediaSession-Start.patch @@ -0,0 +1,128 @@ +From f09b36196097597be64e9c0be6e4cb8d5a394028 Mon Sep 17 00:00:00 2001 +From: Zhiyi Zhang +Date: Tue, 1 Aug 2023 10:52:21 +0800 +Subject: [PATCH 01/41] mf: Add seeking support for IMFMediaSession::Start(). + +--- + dlls/mf/session.c | 57 ++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 51 insertions(+), 6 deletions(-) + +diff --git a/dlls/mf/session.c b/dlls/mf/session.c +index ef707dea4de..3f3be2b84b0 100644 +--- a/dlls/mf/session.c ++++ b/dlls/mf/session.c +@@ -110,6 +110,7 @@ enum object_state + OBJ_STATE_STARTED, + OBJ_STATE_PAUSED, + OBJ_STATE_PREROLLED, ++ OBJ_STATE_SEEKING, + OBJ_STATE_INVALID, + }; + +@@ -912,10 +913,28 @@ static HRESULT session_subscribe_sources(struct media_session *session) + return hr; + } + ++static void session_set_source_output_nodes_seeking(struct media_session *session) ++{ ++ struct media_source *source; ++ struct topo_node *node; ++ ++ LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) ++ { ++ source->state = OBJ_STATE_SEEKING; ++ } ++ ++ LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry) ++ { ++ if (node->type == MF_TOPOLOGY_SOURCESTREAM_NODE || node->type == MF_TOPOLOGY_OUTPUT_NODE) ++ node->state = OBJ_STATE_SEEKING; ++ } ++} ++ + static void session_start(struct media_session *session, const GUID *time_format, const PROPVARIANT *start_position) + { + struct media_source *source; + struct topo_node *topo_node; ++ MFTIME duration; + HRESULT hr; + UINT i; + +@@ -932,6 +951,13 @@ static void session_start(struct media_session *session, const GUID *time_format + + /* fallthrough */ + case SESSION_STATE_PAUSED: ++ case SESSION_STATE_STARTED: ++ if (session->state == SESSION_STATE_STARTED && !(session->caps & MFSESSIONCAP_SEEK)) ++ { ++ WARN("Seeking is not supported for this session.\n"); ++ session_command_complete(session); ++ return; ++ } + + session->presentation.time_format = *time_format; + session->presentation.start_position.vt = VT_EMPTY; +@@ -945,6 +971,14 @@ static void session_start(struct media_session *session, const GUID *time_format + + LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) + { ++ hr = IMFPresentationDescriptor_GetUINT64(source->pd, &MF_PD_DURATION, (UINT64 *)&duration); ++ if (SUCCEEDED(hr) && start_position->vt == VT_I8&& start_position->hVal.QuadPart > duration) ++ { ++ WARN("Start position %s out of range, hr %#lx.\n", wine_dbgstr_longlong(start_position->hVal.QuadPart), hr); ++ session_command_complete_with_event(session, MESessionStarted, MF_E_INVALID_POSITION, NULL); ++ return; ++ } ++ + if (FAILED(hr = IMFMediaSource_Start(source->source, source->pd, &GUID_NULL, start_position))) + { + WARN("Failed to start media source %p, hr %#lx.\n", source->source, hr); +@@ -965,12 +999,22 @@ static void session_start(struct media_session *session, const GUID *time_format + } + } + ++ if (session->state == SESSION_STATE_STARTED) ++ { ++ struct topo_node *node; ++ ++ LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry) ++ { ++ if (node->type == MF_TOPOLOGY_OUTPUT_NODE) ++ IMFStreamSink_Flush(node->object.sink_stream); ++ else if (node->type == MF_TOPOLOGY_TRANSFORM_NODE) ++ IMFTransform_ProcessMessage(node->object.transform, MFT_MESSAGE_COMMAND_FLUSH, 0); ++ } ++ ++ session_set_source_output_nodes_seeking(session); ++ } + session->state = SESSION_STATE_STARTING_SOURCES; + break; +- case SESSION_STATE_STARTED: +- FIXME("Seeking is not implemented.\n"); +- session_command_complete(session); +- break; + default: + session_command_complete_with_event(session, MESessionStarted, MF_E_INVALIDREQUEST, NULL); + break; +@@ -2206,6 +2250,9 @@ static HRESULT WINAPI mfsession_Start(IMFMediaSession *iface, const GUID *format + if (!start_position) + return E_POINTER; + ++ if (FAILED(hr = session_is_shut_down(session))) ++ return hr; ++ + if (FAILED(hr = create_session_op(SESSION_CMD_START, &op))) + return hr; + +@@ -3714,8 +3761,6 @@ static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IM + { + case MESourceSeeked: + case MEStreamSeeked: +- FIXME("Source/stream seeking, semi-stub!\n"); +- /* fallthrough */ + case MESourceStarted: + case MESourcePaused: + case MESourceStopped: +-- +2.45.1 + diff --git a/patches/wine-gst/0002-mf-tests-Add-a-create_media_session_with_source_sink.patch b/patches/wine-gst/0002-mf-tests-Add-a-create_media_session_with_source_sink.patch new file mode 100644 index 000000000..dcc1c3d5f --- /dev/null +++ b/patches/wine-gst/0002-mf-tests-Add-a-create_media_session_with_source_sink.patch @@ -0,0 +1,143 @@ +From 13e5f023ec606fccf3d24e532e9bf4f11871107a Mon Sep 17 00:00:00 2001 +From: Zhiyi Zhang +Date: Tue, 8 Aug 2023 15:24:34 +0800 +Subject: [PATCH 02/41] mf/tests: Add a create_media_session_with_source_sink() + helper. + +--- + dlls/mf/tests/mf.c | 92 ++++++++++++++++++++++++---------------------- + 1 file changed, 48 insertions(+), 44 deletions(-) + +diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c +index 0a34329bd75..e0bcedac20f 100644 +--- a/dlls/mf/tests/mf.c ++++ b/dlls/mf/tests/mf.c +@@ -4995,6 +4995,53 @@ static void test_sample_grabber_is_mediatype_supported(void) + IMFSampleGrabberSinkCallback_Release(grabber_callback); + } + ++/* create a media session with the specified source and sink */ ++static void create_media_session_with_source_sink(IMFMediaSource *source, IMFActivate *sink_activate, ++ IMFMediaSession **session) ++{ ++ IMFTopologyNode *src_node, *sink_node; ++ IMFPresentationDescriptor *pd; ++ IMFStreamDescriptor *sd; ++ IMFTopology *topology; ++ BOOL selected; ++ HRESULT hr; ++ ++ hr = MFCreateMediaSession(NULL, session); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = MFCreateTopology(&topology); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFTopology_AddNode(topology, sink_node); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFTopology_AddNode(topology, src_node); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFMediaSource_CreatePresentationDescriptor(source, &pd); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 0, &selected, &sd); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok(selected, "got selected %u.\n", !!selected); ++ init_source_node(source, -1, src_node, pd, sd); ++ hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate); ++ ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr); ++ hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_ALLOW_DECODER); ++ ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr); ++ hr = IMFTopology_SetUINT32(topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, TRUE); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFMediaSession_SetTopology(*session, 0, topology); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ IMFStreamDescriptor_Release(sd); ++ IMFPresentationDescriptor_Release(pd); ++ IMFTopologyNode_Release(src_node); ++ IMFTopologyNode_Release(sink_node); ++ IMFTopology_Release(topology); ++} ++ + static void test_sample_grabber_orientation(GUID subtype) + { + media_type_desc video_rgb32_desc = +@@ -5004,17 +5051,12 @@ static void test_sample_grabber_orientation(GUID subtype) + }; + + struct test_grabber_callback *grabber_callback; +- IMFTopologyNode *src_node, *sink_node; +- IMFPresentationDescriptor *pd; + IMFAsyncCallback *callback; + IMFActivate *sink_activate; + IMFMediaType *output_type; + IMFMediaSession *session; +- IMFStreamDescriptor *sd; + IMFMediaSource *source; +- IMFTopology *topology; + PROPVARIANT propvar; +- BOOL selected; + HRESULT hr; + DWORD res; + +@@ -5035,33 +5077,6 @@ static void test_sample_grabber_orientation(GUID subtype) + grabber_callback->done_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!grabber_callback->done_event, "CreateEventW failed, error %lu\n", GetLastError()); + +- hr = MFCreateMediaSession(NULL, &session); +- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +- +- hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node); +- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +- hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node); +- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +- +- hr = MFCreateTopology(&topology); +- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +- hr = IMFTopology_AddNode(topology, sink_node); +- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +- hr = IMFTopology_AddNode(topology, src_node); +- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +- hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0); +- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +- +- hr = IMFMediaSource_CreatePresentationDescriptor(source, &pd); +- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +- hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 0, &selected, &sd); +- ok(selected, "got selected %u.\n", !!selected); +- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +- init_source_node(source, -1, src_node, pd, sd); +- IMFTopologyNode_Release(src_node); +- IMFPresentationDescriptor_Release(pd); +- IMFStreamDescriptor_Release(sd); +- + hr = MFCreateMediaType(&output_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(output_type, video_rgb32_desc, -1); +@@ -5069,18 +5084,7 @@ static void test_sample_grabber_orientation(GUID subtype) + ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr); + IMFMediaType_Release(output_type); + +- hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate); +- ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr); +- hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_ALLOW_DECODER); +- ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr); +- IMFTopologyNode_Release(sink_node); +- +- hr = IMFTopology_SetUINT32(topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, TRUE); +- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +- +- hr = IMFMediaSession_SetTopology(session, 0, topology); +- ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +- IMFTopology_Release(topology); ++ create_media_session_with_source_sink(source, sink_activate, &session); + + propvar.vt = VT_EMPTY; + hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); +-- +2.45.1 + diff --git a/patches/wine-gst/0003-mf-tests-Test-IMFMediaSession-Start.patch b/patches/wine-gst/0003-mf-tests-Test-IMFMediaSession-Start.patch new file mode 100644 index 000000000..5b8cfeafc --- /dev/null +++ b/patches/wine-gst/0003-mf-tests-Test-IMFMediaSession-Start.patch @@ -0,0 +1,784 @@ +From f681e846b69740f0a29916c06d83226f1511a194 Mon Sep 17 00:00:00 2001 +From: Zhiyi Zhang +Date: Mon, 7 Aug 2023 11:52:20 +0800 +Subject: [PATCH 03/41] mf/tests: Test IMFMediaSession::Start(). + +--- + dlls/mf/tests/mf.c | 704 ++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 696 insertions(+), 8 deletions(-) + +diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c +index e0bcedac20f..f164a04b989 100644 +--- a/dlls/mf/tests/mf.c ++++ b/dlls/mf/tests/mf.c +@@ -2086,6 +2086,448 @@ static IMFMediaSource *create_media_source(const WCHAR *name, const WCHAR *mime) + return source; + } + ++enum source_state ++{ ++ SOURCE_STOPPED = 0, ++ SOURCE_RUNNING, ++}; ++ ++struct test_media_stream ++{ ++ IMFMediaStream IMFMediaStream_iface; ++ IMFMediaEventQueue *event_queue; ++ IMFStreamDescriptor *sd; ++ IMFMediaSource *source; ++ LONGLONG sample_duration; ++ LONGLONG sample_time; ++ BOOL is_new; ++ LONG refcount; ++}; ++ ++static struct test_media_stream *impl_from_IMFMediaStream(IMFMediaStream *iface) ++{ ++ return CONTAINING_RECORD(iface, struct test_media_stream, IMFMediaStream_iface); ++} ++ ++static HRESULT WINAPI test_media_stream_QueryInterface(IMFMediaStream *iface, REFIID riid, void **out) ++{ ++ if (IsEqualIID(riid, &IID_IMFMediaStream) ++ || IsEqualIID(riid, &IID_IMFMediaEventGenerator) ++ || IsEqualIID(riid, &IID_IUnknown)) ++ { ++ *out = iface; ++ } ++ else ++ { ++ *out = NULL; ++ return E_NOINTERFACE; ++ } ++ ++ IMFMediaStream_AddRef(iface); ++ return S_OK; ++} ++ ++static ULONG WINAPI test_media_stream_AddRef(IMFMediaStream *iface) ++{ ++ struct test_media_stream *stream = impl_from_IMFMediaStream(iface); ++ return InterlockedIncrement(&stream->refcount); ++} ++ ++static ULONG WINAPI test_media_stream_Release(IMFMediaStream *iface) ++{ ++ struct test_media_stream *stream = impl_from_IMFMediaStream(iface); ++ ULONG refcount = InterlockedDecrement(&stream->refcount); ++ ++ if (!refcount) ++ { ++ IMFMediaEventQueue_Release(stream->event_queue); ++ free(stream); ++ } ++ ++ return refcount; ++} ++ ++static HRESULT WINAPI test_media_stream_GetEvent(IMFMediaStream *iface, DWORD flags, IMFMediaEvent **event) ++{ ++ struct test_media_stream *stream = impl_from_IMFMediaStream(iface); ++ return IMFMediaEventQueue_GetEvent(stream->event_queue, flags, event); ++} ++ ++static HRESULT WINAPI test_media_stream_BeginGetEvent(IMFMediaStream *iface, IMFAsyncCallback *callback, IUnknown *state) ++{ ++ struct test_media_stream *stream = impl_from_IMFMediaStream(iface); ++ return IMFMediaEventQueue_BeginGetEvent(stream->event_queue, callback, state); ++} ++ ++static HRESULT WINAPI test_media_stream_EndGetEvent(IMFMediaStream *iface, IMFAsyncResult *result, IMFMediaEvent **event) ++{ ++ struct test_media_stream *stream = impl_from_IMFMediaStream(iface); ++ return IMFMediaEventQueue_EndGetEvent(stream->event_queue, result, event); ++} ++ ++static HRESULT WINAPI test_media_stream_QueueEvent(IMFMediaStream *iface, MediaEventType event_type, REFGUID ext_type, ++ HRESULT hr, const PROPVARIANT *value) ++{ ++ struct test_media_stream *stream = impl_from_IMFMediaStream(iface); ++ return IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, event_type, ext_type, hr, value); ++} ++ ++static HRESULT WINAPI test_media_stream_GetMediaSource(IMFMediaStream *iface, IMFMediaSource **source) ++{ ++ struct test_media_stream *stream = impl_from_IMFMediaStream(iface); ++ ++ *source = stream->source; ++ IMFMediaSource_AddRef(*source); ++ ++ return S_OK; ++} ++ ++static HRESULT WINAPI test_media_stream_GetStreamDescriptor(IMFMediaStream *iface, IMFStreamDescriptor **sd) ++{ ++ struct test_media_stream *stream = impl_from_IMFMediaStream(iface); ++ ++ *sd = stream->sd; ++ IMFStreamDescriptor_AddRef(*sd); ++ ++ return S_OK; ++} ++ ++static HRESULT WINAPI test_media_stream_RequestSample(IMFMediaStream *iface, IUnknown *token) ++{ ++ struct test_media_stream *stream = impl_from_IMFMediaStream(iface); ++ IMFMediaBuffer *buffer; ++ IMFSample *sample; ++ HRESULT hr; ++ ++ hr = MFCreateSample(&sample); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ if (stream->sample_duration) ++ { ++ hr = IMFSample_SetSampleDuration(sample, stream->sample_duration); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ hr = IMFSample_SetSampleTime(sample, stream->sample_time); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ stream->sample_time += stream->sample_duration; ++ } ++ else ++ { ++ hr = IMFSample_SetSampleTime(sample, 123); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ hr = IMFSample_SetSampleDuration(sample, 1); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ } ++ ++ if (token) ++ IMFSample_SetUnknown(sample, &MFSampleExtension_Token, token); ++ ++ /* Reader expects buffers, empty samples are considered an error. */ ++ hr = MFCreateMemoryBuffer(8, &buffer); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFSample_AddBuffer(sample, buffer); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ IMFMediaBuffer_Release(buffer); ++ ++ hr = IMFMediaEventQueue_QueueEventParamUnk(stream->event_queue, MEMediaSample, &GUID_NULL, S_OK, ++ (IUnknown *)sample); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ IMFSample_Release(sample); ++ ++ return S_OK; ++} ++ ++static const IMFMediaStreamVtbl test_media_stream_vtbl = ++{ ++ test_media_stream_QueryInterface, ++ test_media_stream_AddRef, ++ test_media_stream_Release, ++ test_media_stream_GetEvent, ++ test_media_stream_BeginGetEvent, ++ test_media_stream_EndGetEvent, ++ test_media_stream_QueueEvent, ++ test_media_stream_GetMediaSource, ++ test_media_stream_GetStreamDescriptor, ++ test_media_stream_RequestSample, ++}; ++ ++#define TEST_SOURCE_NUM_STREAMS 3 ++ ++struct unseekable_source ++{ ++ IMFMediaSource IMFMediaSource_iface; ++ IMFMediaEventQueue *event_queue; ++ IMFPresentationDescriptor *pd; ++ struct test_media_stream *streams[TEST_SOURCE_NUM_STREAMS]; ++ enum source_state state; ++ unsigned stream_count; ++ CRITICAL_SECTION cs; ++ LONG refcount; ++}; ++ ++static struct unseekable_source *impl_unseekable_source_from_IMFMediaSource(IMFMediaSource *iface) ++{ ++ return CONTAINING_RECORD(iface, struct unseekable_source, IMFMediaSource_iface); ++} ++ ++static HRESULT WINAPI unseekable_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out) ++{ ++ if (IsEqualIID(riid, &IID_IMFMediaSource) ++ || IsEqualIID(riid, &IID_IMFMediaEventGenerator) ++ || IsEqualIID(riid, &IID_IUnknown)) ++ { ++ *out = iface; ++ } ++ else ++ { ++ *out = NULL; ++ return E_NOINTERFACE; ++ } ++ ++ IMFMediaSource_AddRef(iface); ++ return S_OK; ++} ++ ++static ULONG WINAPI unseekable_source_AddRef(IMFMediaSource *iface) ++{ ++ struct unseekable_source *source = impl_unseekable_source_from_IMFMediaSource(iface); ++ return InterlockedIncrement(&source->refcount); ++} ++ ++static ULONG WINAPI unseekable_source_Release(IMFMediaSource *iface) ++{ ++ struct unseekable_source *source = impl_unseekable_source_from_IMFMediaSource(iface); ++ ULONG refcount = InterlockedDecrement(&source->refcount); ++ ++ if (!refcount) ++ { ++ IMFMediaEventQueue_Release(source->event_queue); ++ free(source); ++ } ++ ++ return refcount; ++} ++ ++static HRESULT WINAPI unseekable_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event) ++{ ++ struct unseekable_source *source = impl_unseekable_source_from_IMFMediaSource(iface); ++ return IMFMediaEventQueue_GetEvent(source->event_queue, flags, event); ++} ++ ++static HRESULT WINAPI unseekable_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state) ++{ ++ struct unseekable_source *source = impl_unseekable_source_from_IMFMediaSource(iface); ++ return IMFMediaEventQueue_BeginGetEvent(source->event_queue, callback, state); ++} ++ ++static HRESULT WINAPI unseekable_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event) ++{ ++ struct unseekable_source *source = impl_unseekable_source_from_IMFMediaSource(iface); ++ return IMFMediaEventQueue_EndGetEvent(source->event_queue, result, event); ++} ++ ++static HRESULT WINAPI unseekable_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type, ++ HRESULT hr, const PROPVARIANT *value) ++{ ++ struct unseekable_source *source = impl_unseekable_source_from_IMFMediaSource(iface); ++ return IMFMediaEventQueue_QueueEventParamVar(source->event_queue, event_type, ext_type, hr, value); ++} ++ ++static HRESULT WINAPI unseekable_source_GetCharacteristics(IMFMediaSource *iface, DWORD *flags) ++{ ++ *flags = 0; ++ return S_OK; ++} ++ ++static HRESULT WINAPI unseekable_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **pd) ++{ ++ struct unseekable_source *source = impl_unseekable_source_from_IMFMediaSource(iface); ++ IMFStreamDescriptor *sds[ARRAY_SIZE(source->streams)]; ++ IMFMediaType *media_type; ++ HRESULT hr = S_OK; ++ int i; ++ ++ EnterCriticalSection(&source->cs); ++ ++ if (source->pd) ++ { ++ *pd = source->pd; ++ IMFPresentationDescriptor_AddRef(*pd); ++ } ++ else ++ { ++ for (i = 0; i < source->stream_count; ++i) ++ { ++ hr = MFCreateMediaType(&media_type); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ hr = MFCreateStreamDescriptor(i, 1, &media_type, &sds[i]); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ IMFMediaType_Release(media_type); ++ } ++ ++ hr = MFCreatePresentationDescriptor(source->stream_count, sds, &source->pd); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFPresentationDescriptor_SetUINT64(source->pd, &MF_PD_DURATION, 10*10000000); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFPresentationDescriptor_SelectStream(source->pd, 0); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ for (i = 0; i < source->stream_count; ++i) ++ IMFStreamDescriptor_Release(sds[i]); ++ ++ *pd = source->pd; ++ IMFPresentationDescriptor_AddRef(*pd); ++ } ++ ++ LeaveCriticalSection(&source->cs); ++ ++ return hr; ++} ++ ++static BOOL is_stream_selected(IMFPresentationDescriptor *pd, DWORD index) ++{ ++ IMFStreamDescriptor *sd; ++ BOOL selected = FALSE; ++ ++ if (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, index, &selected, &sd))) ++ IMFStreamDescriptor_Release(sd); ++ ++ return selected; ++} ++ ++static HRESULT WINAPI unseekable_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *pd, const GUID *time_format, ++ const PROPVARIANT *start_position) ++{ ++ struct unseekable_source *source = impl_unseekable_source_from_IMFMediaSource(iface); ++ MediaEventType event_type; ++ PROPVARIANT var; ++ HRESULT hr; ++ int i; ++ ++ ok(time_format && IsEqualGUID(time_format, &GUID_NULL), "Unexpected time format %s.\n", ++ wine_dbgstr_guid(time_format)); ++ ok(start_position && (start_position->vt == VT_I8 || start_position->vt == VT_EMPTY), ++ "Unexpected position type.\n"); ++ ++ EnterCriticalSection(&source->cs); ++ ++ event_type = source->state == SOURCE_RUNNING ? MESourceSeeked : MESourceStarted; ++ hr = IMFMediaEventQueue_QueueEventParamVar(source->event_queue, event_type, &GUID_NULL, S_OK, NULL); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ for (i = 0; i < source->stream_count; ++i) ++ { ++ if (!is_stream_selected(pd, i)) ++ continue; ++ ++ var.vt = VT_UNKNOWN; ++ var.punkVal = (IUnknown *)&source->streams[i]->IMFMediaStream_iface; ++ event_type = source->streams[i]->is_new ? MENewStream : MEUpdatedStream; ++ source->streams[i]->is_new = FALSE; ++ hr = IMFMediaEventQueue_QueueEventParamVar(source->event_queue, event_type, &GUID_NULL, S_OK, &var); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ event_type = source->state == SOURCE_RUNNING ? MEStreamSeeked : MEStreamStarted; ++ hr = IMFMediaEventQueue_QueueEventParamVar(source->streams[i]->event_queue, event_type, &GUID_NULL, ++ S_OK, NULL); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ } ++ ++ source->state = SOURCE_RUNNING; ++ ++ LeaveCriticalSection(&source->cs); ++ ++ return S_OK; ++} ++ ++static HRESULT WINAPI unseekable_source_Stop(IMFMediaSource *iface) ++{ ++ return S_OK; ++} ++ ++static HRESULT WINAPI unseekable_source_Pause(IMFMediaSource *iface) ++{ ++ ok(0, "Unexpected call.\n"); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI unseekable_source_Shutdown(IMFMediaSource *iface) ++{ ++ struct unseekable_source *source = impl_unseekable_source_from_IMFMediaSource(iface); ++ HRESULT hr; ++ ++ hr = IMFMediaEventQueue_Shutdown(source->event_queue); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ return S_OK; ++} ++ ++static const IMFMediaSourceVtbl unseekable_source_vtbl = ++{ ++ unseekable_source_QueryInterface, ++ unseekable_source_AddRef, ++ unseekable_source_Release, ++ unseekable_source_GetEvent, ++ unseekable_source_BeginGetEvent, ++ unseekable_source_EndGetEvent, ++ unseekable_source_QueueEvent, ++ unseekable_source_GetCharacteristics, ++ unseekable_source_CreatePresentationDescriptor, ++ unseekable_source_Start, ++ unseekable_source_Stop, ++ unseekable_source_Pause, ++ unseekable_source_Shutdown, ++}; ++ ++static struct test_media_stream *create_test_stream(DWORD stream_index, IMFMediaSource *source) ++{ ++ struct test_media_stream *stream; ++ IMFPresentationDescriptor *pd; ++ BOOL selected; ++ HRESULT hr; ++ ++ stream = calloc(1, sizeof(*stream)); ++ stream->IMFMediaStream_iface.lpVtbl = &test_media_stream_vtbl; ++ stream->refcount = 1; ++ hr = MFCreateEventQueue(&stream->event_queue); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ stream->source = source; ++ IMFMediaSource_AddRef(stream->source); ++ stream->is_new = TRUE; ++ ++ IMFMediaSource_CreatePresentationDescriptor(source, &pd); ++ IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, stream_index, &selected, &stream->sd); ++ IMFPresentationDescriptor_Release(pd); ++ ++ return stream; ++} ++ ++static IMFMediaSource *create_unseekable_source(void) ++{ ++ struct unseekable_source *source; ++ int i; ++ ++ source = calloc(1, sizeof(*source)); ++ source->IMFMediaSource_iface.lpVtbl = &unseekable_source_vtbl; ++ source->refcount = 1; ++ source->stream_count = 1; ++ MFCreateEventQueue(&source->event_queue); ++ InitializeCriticalSection(&source->cs); ++ for (i = 0; i < source->stream_count; ++i) ++ source->streams[i] = create_test_stream(i, &source->IMFMediaSource_iface); ++ ++ return &source->IMFMediaSource_iface; ++} ++ + static void test_media_session_events(void) + { + static const media_type_desc audio_float_44100 = +@@ -2887,27 +3329,27 @@ static ULONG WINAPI test_grabber_callback_Release(IMFSampleGrabberSinkCallback * + + static HRESULT WINAPI test_grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME time, LONGLONG offset) + { +- return E_NOTIMPL; ++ return S_OK; + } + + static HRESULT WINAPI test_grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME time) + { +- return E_NOTIMPL; ++ return S_OK; + } + + static HRESULT WINAPI test_grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME time) + { +- return E_NOTIMPL; ++ return S_OK; + } + + static HRESULT WINAPI test_grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME time) + { +- return E_NOTIMPL; ++ return S_OK; + } + + static HRESULT WINAPI test_grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME time, float rate) + { +- return E_NOTIMPL; ++ return S_OK; + } + + static HRESULT WINAPI test_grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface, +@@ -4995,9 +5437,9 @@ static void test_sample_grabber_is_mediatype_supported(void) + IMFSampleGrabberSinkCallback_Release(grabber_callback); + } + +-/* create a media session with the specified source and sink */ ++/* create a media session with the specified source and sink, and return duration if required */ + static void create_media_session_with_source_sink(IMFMediaSource *source, IMFActivate *sink_activate, +- IMFMediaSession **session) ++ IMFMediaSession **session, UINT64 *duration) + { + IMFTopologyNode *src_node, *sink_node; + IMFPresentationDescriptor *pd; +@@ -5025,6 +5467,11 @@ static void create_media_session_with_source_sink(IMFMediaSource *source, IMFAct + hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 0, &selected, &sd); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(selected, "got selected %u.\n", !!selected); ++ if (duration) ++ { ++ hr = IMFPresentationDescriptor_GetUINT64(pd, &MF_PD_DURATION, duration); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ } + init_source_node(source, -1, src_node, pd, sd); + hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate); + ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr); +@@ -5084,7 +5531,7 @@ static void test_sample_grabber_orientation(GUID subtype) + ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr); + IMFMediaType_Release(output_type); + +- create_media_session_with_source_sink(source, sink_activate, &session); ++ create_media_session_with_source_sink(source, sink_activate, &session, NULL); + + propvar.vt = VT_EMPTY; + hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); +@@ -7280,6 +7727,246 @@ static void test_MFCreateSequencerSegmentOffset(void) + PropVariantClear(&propvar); + } + ++static void test_media_session_Start(void) ++{ ++ media_type_desc video_rgb32_desc = ++ { ++ ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ++ ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), ++ }; ++ static const MFTIME allowed_error = 500000; ++ struct test_grabber_callback *grabber_callback; ++ IMFPresentationClock *presentation_clock; ++ IMFActivate *sink_activate; ++ IMFAsyncCallback *callback; ++ IMFMediaType *output_type; ++ IMFMediaSession *session; ++ IMFMediaSource *source; ++ MFTIME time, old_time; ++ PROPVARIANT propvar; ++ IMFClock *clock; ++ UINT64 duration; ++ DWORD caps; ++ HRESULT hr; ++ ++ hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ++ ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr); ++ ++ if (!(source = create_media_source(L"test.mp4", L"video/mp4"))) ++ { ++ win_skip("MP4 media source is not supported, skipping tests.\n"); ++ MFShutdown(); ++ return; ++ } ++ ++ grabber_callback = impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback()); ++ hr = MFCreateMediaType(&output_type); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ init_media_type(output_type, video_rgb32_desc, -1); ++ hr = MFCreateSampleGrabberSinkActivate(output_type, &grabber_callback->IMFSampleGrabberSinkCallback_iface, &sink_activate); ++ ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr); ++ IMFMediaType_Release(output_type); ++ create_media_session_with_source_sink(source, sink_activate, &session, &duration); ++ ++ hr = IMFMediaSession_GetClock(session, &clock); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFClock_QueryInterface(clock, &IID_IMFPresentationClock, (void **)&presentation_clock); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ IMFClock_Release(clock); ++ ++ propvar.vt = VT_EMPTY; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ callback = create_test_callback(TRUE); ++ hr = wait_media_event(session, callback, MESessionStarted, 5000, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ /* Seek to 1s */ ++ propvar.vt = VT_I8; ++ propvar.hVal.QuadPart = 10000000; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = wait_media_event(session, callback, MESessionStarted, 1000, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFPresentationClock_GetTime(presentation_clock, &time); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok(llabs(time - 10000000) <= allowed_error, "Unexpected time %I64d.\n", time); ++ ++ /* Seek to beyond duration */ ++ propvar.vt = VT_I8; ++ propvar.hVal.QuadPart = duration + 10000000; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = wait_media_event(session, callback, MESessionStarted, 1000, &propvar); ++ ok(hr == MF_E_INVALID_POSITION, "Unexpected hr %#lx.\n", hr); ++ hr = IMFPresentationClock_GetTime(presentation_clock, &time); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok(llabs(time - 10000000) <= allowed_error, "Unexpected time %I64d.\n", time); ++ ++ /* Seek to negative position */ ++ propvar.vt = VT_I8; ++ propvar.hVal.QuadPart = -10000000; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = wait_media_event(session, callback, MESessionStarted, 1000, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFPresentationClock_GetTime(presentation_clock, &time); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok(llabs(time - (-10000000)) <= allowed_error, "Unexpected time %I64d.\n", time); ++ ++ /* Seek backwards to 0s */ ++ propvar.vt = VT_I8; ++ propvar.hVal.QuadPart = 0; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = wait_media_event(session, callback, MESessionStarted, 1000, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFPresentationClock_GetTime(presentation_clock, &time); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok(llabs(time) <= allowed_error, "Unexpected time %I64d.\n", time); ++ ++ /* Seek to 1s while in paused state */ ++ hr = IMFMediaSession_Pause(session); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = wait_media_event(session, callback, MESessionPaused, 1000, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ propvar.vt = VT_I8; ++ propvar.hVal.QuadPart = 10000000; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = wait_media_event(session, callback, MESessionStarted, 1000, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ hr = IMFPresentationClock_GetTime(presentation_clock, &time); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok(llabs(time - 10000000) <= allowed_error, "Unexpected time %I64d.\n", time); ++ old_time = time; ++ ++ /* Expected the presentation clock is running */ ++ Sleep(100); ++ hr = IMFPresentationClock_GetTime(presentation_clock, &time); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok(time > old_time, "Unexpected time %I64d.\n", time); ++ ++ hr = IMFMediaSession_Stop(session); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFMediaSession_Close(session); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ /* Media session is shut down */ ++ hr = IMFMediaSource_Shutdown(source); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFMediaSession_Shutdown(session); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ propvar.vt = VT_I8; ++ propvar.hVal.QuadPart = 10000000; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, NULL); ++ ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); ++ ++ propvar.vt = VT_I8; ++ propvar.hVal.QuadPart = 10000000; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); ++ ++ propvar.vt = VT_EMPTY; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); ++ ++ IMFPresentationClock_Release(presentation_clock); ++ IMFMediaSession_Release(session); ++ IMFMediaSource_Release(source); ++ IMFActivate_ShutdownObject(sink_activate); ++ IMFActivate_Release(sink_activate); ++ IMFSampleGrabberSinkCallback_Release(&grabber_callback->IMFSampleGrabberSinkCallback_iface); ++ ++ /* Unseekable media source */ ++ source = create_unseekable_source(); ++ hr = IMFMediaSource_GetCharacteristics(source, &caps); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok((caps & MFMEDIASOURCE_CAN_SEEK) == 0, "Got unexpected caps %#lx.\n", caps); ++ grabber_callback = impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback()); ++ hr = MFCreateMediaType(&output_type); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ init_media_type(output_type, video_rgb32_desc, -1); ++ hr = MFCreateSampleGrabberSinkActivate(output_type, &grabber_callback->IMFSampleGrabberSinkCallback_iface, &sink_activate); ++ ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr); ++ IMFMediaType_Release(output_type); ++ create_media_session_with_source_sink(source, sink_activate, &session, &duration); ++ ++ hr = IMFMediaSession_GetClock(session, &clock); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFClock_QueryInterface(clock, &IID_IMFPresentationClock, (void **)&presentation_clock); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ IMFClock_Release(clock); ++ ++ propvar.vt = VT_EMPTY; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ callback = create_test_callback(TRUE); ++ hr = wait_media_event(session, callback, MESessionStarted, 1000, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ hr = IMFMediaSession_GetSessionCapabilities(session, &caps); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok((caps & MFSESSIONCAP_SEEK) == 0, "Got unexpected caps %#lx\n", caps); ++ ++ /* Seek to 1s */ ++ propvar.vt = VT_I8; ++ propvar.hVal.QuadPart = 10000000; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ /* Waiting for MESessionStarted will timeout, skip checking MESessionStarted */ ++ hr = IMFPresentationClock_GetTime(presentation_clock, &time); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok(llabs(time) <= allowed_error, "Unexpected time %I64d.\n", time); ++ ++ /* Seek to 0s */ ++ propvar.vt = VT_EMPTY; ++ propvar.hVal.QuadPart = 0; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ /* Waiting for MESessionStarted will timeout, skip checking MESessionStarted */ ++ hr = IMFPresentationClock_GetTime(presentation_clock, &time); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok(llabs(time) <= allowed_error, "Unexpected time %I64d.\n", time); ++ ++ /* Seek backwards to 0s */ ++ Sleep(200); ++ hr = IMFPresentationClock_GetTime(presentation_clock, &time); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok(llabs(time - 2000000) <= allowed_error, "Unexpected time %I64d.\n", time); ++ ++ propvar.vt = VT_I8; ++ propvar.hVal.QuadPart = 0; ++ hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ /* Waiting for MESessionStarted will timeout, skip checking MESessionStarted */ ++ hr = IMFPresentationClock_GetTime(presentation_clock, &time); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ok(llabs(time - 2000000) <= allowed_error, "Unexpected time %I64d.\n", time); ++ ++ hr = IMFMediaSession_Stop(session); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFMediaSession_Close(session); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFMediaSession_Shutdown(session); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ hr = IMFMediaSource_Shutdown(source); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ IMFPresentationClock_Release(presentation_clock); ++ IMFMediaSession_Release(session); ++ IMFMediaSource_Release(source); ++ IMFActivate_ShutdownObject(sink_activate); ++ IMFActivate_Release(sink_activate); ++ IMFSampleGrabberSinkCallback_Release(&grabber_callback->IMFSampleGrabberSinkCallback_iface); ++ ++ hr = MFShutdown(); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++} ++ + START_TEST(mf) + { + init_functions(); +@@ -7316,4 +8003,5 @@ START_TEST(mf) + test_MFRequireProtectedEnvironment(); + test_mpeg4_media_sink(); + test_MFCreateSequencerSegmentOffset(); ++ test_media_session_Start(); + } +-- +2.45.1 + diff --git a/patches/wine-gst/0004-mfmediaengine-Implement-IMFMediaEngineEx-SetCurrentT.patch b/patches/wine-gst/0004-mfmediaengine-Implement-IMFMediaEngineEx-SetCurrentT.patch new file mode 100644 index 000000000..e673a2efc --- /dev/null +++ b/patches/wine-gst/0004-mfmediaengine-Implement-IMFMediaEngineEx-SetCurrentT.patch @@ -0,0 +1,109 @@ +From 489c23245659d54c0da0def91209d4016e9a1117 Mon Sep 17 00:00:00 2001 +From: Zhiyi Zhang +Date: Fri, 28 Jul 2023 18:04:30 +0800 +Subject: [PATCH 04/41] mfmediaengine: Implement + IMFMediaEngineEx::SetCurrentTime/Ex(). + +--- + dlls/mfmediaengine/main.c | 62 +++++++++++++++++++++++++++++---------- + 1 file changed, 47 insertions(+), 15 deletions(-) + +diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c +index 9e41d9dad84..28a273616c8 100644 +--- a/dlls/mfmediaengine/main.c ++++ b/dlls/mfmediaengine/main.c +@@ -96,6 +96,7 @@ enum media_engine_flags + FLAGS_ENGINE_NEW_FRAME = 0x8000, + FLAGS_ENGINE_SOURCE_PENDING = 0x10000, + FLAGS_ENGINE_PLAY_PENDING = 0x20000, ++ FLAGS_ENGINE_SEEKING = 0x40000, + }; + + struct vec3 +@@ -982,7 +983,14 @@ static HRESULT WINAPI media_engine_session_events_Invoke(IMFAsyncCallback *iface + break; + } + case MESessionStarted: +- ++ EnterCriticalSection(&engine->cs); ++ if (engine->flags & FLAGS_ENGINE_SEEKING) ++ { ++ media_engine_set_flag(engine, FLAGS_ENGINE_SEEKING | FLAGS_ENGINE_IS_ENDED, FALSE); ++ IMFMediaEngineNotify_EventNotify(engine->callback, MF_MEDIA_ENGINE_EVENT_SEEKED, 0, 0); ++ IMFMediaEngineNotify_EventNotify(engine->callback, MF_MEDIA_ENGINE_EVENT_TIMEUPDATE, 0, 0); ++ } ++ LeaveCriticalSection(&engine->cs); + IMFMediaEngineNotify_EventNotify(engine->callback, MF_MEDIA_ENGINE_EVENT_PLAYING, 0, 0); + break; + case MESessionEnded: +@@ -1846,19 +1854,9 @@ static double WINAPI media_engine_GetCurrentTime(IMFMediaEngineEx *iface) + + static HRESULT WINAPI media_engine_SetCurrentTime(IMFMediaEngineEx *iface, double time) + { +- struct media_engine *engine = impl_from_IMFMediaEngineEx(iface); +- HRESULT hr = E_NOTIMPL; ++ TRACE("%p, %f.\n", iface, time); + +- FIXME("(%p, %f): stub.\n", iface, time); +- +- EnterCriticalSection(&engine->cs); +- +- if (engine->flags & FLAGS_ENGINE_SHUT_DOWN) +- hr = MF_E_SHUTDOWN; +- +- LeaveCriticalSection(&engine->cs); +- +- return hr; ++ return IMFMediaEngineEx_SetCurrentTimeEx(iface, time, MF_MEDIA_ENGINE_SEEK_MODE_NORMAL); + } + + static double WINAPI media_engine_GetStartTime(IMFMediaEngineEx *iface) +@@ -3059,9 +3057,43 @@ static HRESULT WINAPI media_engine_SetRealTimeMode(IMFMediaEngineEx *iface, BOOL + + static HRESULT WINAPI media_engine_SetCurrentTimeEx(IMFMediaEngineEx *iface, double seektime, MF_MEDIA_ENGINE_SEEK_MODE mode) + { +- FIXME("%p, %f, %#x stub.\n", iface, seektime, mode); ++ struct media_engine *engine = impl_from_IMFMediaEngineEx(iface); ++ PROPVARIANT position; ++ BOOL paused; ++ DWORD caps; ++ HRESULT hr; + +- return E_NOTIMPL; ++ TRACE("%p, %f, %#x.\n", iface, seektime, mode); ++ ++ if (mode) ++ FIXME("mode %#x is ignored.\n", mode); ++ ++ EnterCriticalSection(&engine->cs); ++ ++ if (engine->flags & FLAGS_ENGINE_SHUT_DOWN) ++ hr = MF_E_SHUTDOWN; ++ else ++ { ++ hr = IMFMediaSession_GetSessionCapabilities(engine->session, &caps); ++ if (SUCCEEDED(hr) && caps & MFSESSIONCAP_SEEK) ++ { ++ paused = IMFMediaEngineEx_IsPaused(iface); ++ ++ position.vt = VT_I8; ++ position.hVal.QuadPart = min(max(0, seektime), engine->duration) * 10000000; ++ hr = IMFMediaSession_Start(engine->session, &GUID_NULL, &position); ++ if (SUCCEEDED(hr)) ++ { ++ media_engine_set_flag(engine, FLAGS_ENGINE_SEEKING, TRUE); ++ IMFMediaEngineNotify_EventNotify(engine->callback, MF_MEDIA_ENGINE_EVENT_SEEKING, 0, 0); ++ if (paused) ++ hr = IMFMediaSession_Pause(engine->session); ++ } ++ } ++ } ++ ++ LeaveCriticalSection(&engine->cs); ++ return hr; + } + + static HRESULT WINAPI media_engine_EnableTimeUpdateTimer(IMFMediaEngineEx *iface, BOOL enable) +-- +2.45.1 + diff --git a/patches/wine-gst/0005-mfmediaengine-tests-Test-IMFMediaEngineEx-SetCurrent.patch b/patches/wine-gst/0005-mfmediaengine-tests-Test-IMFMediaEngineEx-SetCurrent.patch new file mode 100644 index 000000000..1e39ff0dd --- /dev/null +++ b/patches/wine-gst/0005-mfmediaengine-tests-Test-IMFMediaEngineEx-SetCurrent.patch @@ -0,0 +1,243 @@ +From c239555de4e9d8ce25200db06500560f487d8b81 Mon Sep 17 00:00:00 2001 +From: Zhiyi Zhang +Date: Mon, 7 Aug 2023 11:53:41 +0800 +Subject: [PATCH 05/41] mfmediaengine/tests: Test + IMFMediaEngineEx::SetCurrentTime/Ex(). + +--- + dlls/mfmediaengine/tests/mfmediaengine.c | 183 +++++++++++++++++++++++ + 1 file changed, 183 insertions(+) + +diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c +index 47130d8e436..29a11d034cd 100644 +--- a/dlls/mfmediaengine/tests/mfmediaengine.c ++++ b/dlls/mfmediaengine/tests/mfmediaengine.c +@@ -2185,6 +2185,9 @@ struct test_seek_notify + { + IMFMediaEngineNotify IMFMediaEngineNotify_iface; + HANDLE playing_event; ++ HANDLE seeking_event; ++ HANDLE seeked_event; ++ HANDLE time_update_event; + HRESULT expected_error; + HRESULT error; + LONG refcount; +@@ -2224,6 +2227,9 @@ static ULONG WINAPI test_seek_notify_Release(IMFMediaEngineNotify *iface) + if (!refcount) + { + CloseHandle(notify->playing_event); ++ CloseHandle(notify->seeking_event); ++ CloseHandle(notify->seeked_event); ++ CloseHandle(notify->time_update_event); + free(notify); + } + +@@ -2240,6 +2246,15 @@ static HRESULT WINAPI test_seek_notify_EventNotify(IMFMediaEngineNotify *iface, + case MF_MEDIA_ENGINE_EVENT_PLAYING: + SetEvent(notify->playing_event); + break; ++ case MF_MEDIA_ENGINE_EVENT_SEEKING: ++ SetEvent(notify->seeking_event); ++ break; ++ case MF_MEDIA_ENGINE_EVENT_SEEKED: ++ SetEvent(notify->seeked_event); ++ break; ++ case MF_MEDIA_ENGINE_EVENT_TIMEUPDATE: ++ SetEvent(notify->time_update_event); ++ break; + case MF_MEDIA_ENGINE_EVENT_ERROR: + ok(param2 == notify->expected_error, "Unexpected error %#lx\n", param2); + notify->error = param2; +@@ -2264,7 +2279,13 @@ static struct test_seek_notify *create_seek_notify(void) + object = calloc(1, sizeof(*object)); + object->IMFMediaEngineNotify_iface.lpVtbl = &test_seek_notify_vtbl; + object->playing_event = CreateEventW(NULL, FALSE, FALSE, NULL); ++ object->seeking_event = CreateEventW(NULL, FALSE, FALSE, NULL); ++ object->seeked_event = CreateEventW(NULL, FALSE, FALSE, NULL); ++ object->time_update_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!object->playing_event, "Failed to create an event, error %lu.\n", GetLastError()); ++ ok(!!object->seeking_event, "Failed to create an event, error %lu.\n", GetLastError()); ++ ok(!!object->seeked_event, "Failed to create an event, error %lu.\n", GetLastError()); ++ ok(!!object->time_update_event, "Failed to create an event, error %lu.\n", GetLastError()); + object->refcount = 1; + return object; + } +@@ -2510,6 +2531,167 @@ static void test_media_extension(void) + IMFMediaEngineExtension_Release(&extension->IMFMediaEngineExtension_iface); + } + ++#define test_seek_result(a, b, c) _test_seek_result(__LINE__, a, b, c) ++static void _test_seek_result(int line, IMFMediaEngineEx *media_engine, ++ const struct test_seek_notify *notify, double expected_time) ++{ ++ static const double allowed_error = 0.05; ++ static const int timeout = 1000; ++ double time; ++ DWORD res; ++ ++ res = WaitForSingleObject(notify->seeking_event, timeout); ++ ok_(__FILE__, line)(!res, "Waiting for seeking event returned %#lx.\n", res); ++ res = WaitForSingleObject(notify->seeked_event, timeout); ++ ok_(__FILE__, line)(!res, "Waiting for seeked event returned %#lx.\n", res); ++ res = WaitForSingleObject(notify->time_update_event, timeout); ++ ok_(__FILE__, line)(!res, "Waiting for ready event returned %#lx.\n", res); ++ time = IMFMediaEngineEx_GetCurrentTime(media_engine); ++ ok_(__FILE__, line)(compare_double(time, expected_time, allowed_error), "Unexpected time %lf.\n", time); ++} ++ ++static void test_SetCurrentTime(void) ++{ ++ static const double allowed_error = 0.05; ++ static const int timeout = 1000; ++ IMFByteStream *stream, *unseekable_stream = NULL; ++ double time, duration, start, end; ++ struct test_seek_notify *notify; ++ IMFMediaEngineEx *media_engine; ++ HRESULT hr; ++ DWORD res; ++ BOOL ret; ++ BSTR url; ++ ++ notify = create_seek_notify(); ++ media_engine = create_media_engine_ex(¬ify->IMFMediaEngineNotify_iface, NULL, DXGI_FORMAT_B8G8R8X8_UNORM); ++ ok(!!media_engine, "create_media_engine_ex failed.\n"); ++ IMFMediaEngineNotify_Release(¬ify->IMFMediaEngineNotify_iface); ++ ++ stream = load_resource(L"i420-64x64.avi", L"video/avi"); ++ url = SysAllocString(L"i420-64x64.avi"); ++ hr = IMFMediaEngineEx_SetSourceFromByteStream(media_engine, stream, url); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ hr = IMFMediaEngineEx_Play(media_engine); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ res = WaitForSingleObject(notify->playing_event, 5000); ++ ok(!res, "Unexpected res %#lx.\n", res); ++ ++ duration = IMFMediaEngineEx_GetDuration(media_engine); ++ ok(duration > 0, "Got invalid duration.\n"); ++ start = 0; ++ end = duration; ++ ++ /* Test playing state */ ++ hr = IMFMediaEngineEx_SetCurrentTime(media_engine, end); ++ ok(hr == S_OK || broken(hr == MF_INVALID_STATE_ERR) /* Win8 */, "Unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ test_seek_result(media_engine, notify, end); ++ ++ /* Test seeking with a negative position */ ++ hr = IMFMediaEngineEx_SetCurrentTime(media_engine, -1); ++ ok(hr == S_OK || broken(hr == MF_INVALID_STATE_ERR) /* Win8 */, "Unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ test_seek_result(media_engine, notify, 0); ++ ++ /* Test seeking beyond duration */ ++ hr = IMFMediaEngineEx_SetCurrentTime(media_engine, end + 1); ++ ok(hr == S_OK || broken(hr == MF_INVALID_STATE_ERR) /* Win8 */, "Unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ test_seek_result(media_engine, notify, end); ++ ++ hr = IMFMediaEngineEx_SetCurrentTimeEx(media_engine, start, MF_MEDIA_ENGINE_SEEK_MODE_NORMAL); ++ ok(hr == S_OK || broken(hr == MF_INVALID_STATE_ERR) /* Win8 */, "Unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ test_seek_result(media_engine, notify, start); ++ ++ hr = IMFMediaEngineEx_SetCurrentTimeEx(media_engine, end, MF_MEDIA_ENGINE_SEEK_MODE_APPROXIMATE); ++ ok(hr == S_OK || broken(hr == MF_INVALID_STATE_ERR) /* Win8 */, "Unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ test_seek_result(media_engine, notify, end); ++ ++ /* Test paused state */ ++ hr = IMFMediaEngineEx_Pause(media_engine); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ hr = IMFMediaEngineEx_SetCurrentTime(media_engine, start); ++ ok(hr == S_OK || broken(hr == MF_INVALID_STATE_ERR) /* Win8 */, "Unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ { ++ res = WaitForSingleObject(notify->seeking_event, timeout); ++ ok(!res, "Unexpected res %#lx.\n", res); ++ res = WaitForSingleObject(notify->seeked_event, timeout); ++ ok(res == WAIT_TIMEOUT || res == 0, /* No timeout sometimes on Win10+ */ ++ "Unexpected res %#lx.\n", res); ++ res = WaitForSingleObject(notify->time_update_event, timeout); ++ ok(!res, "Unexpected res %#lx.\n", res); ++ time = IMFMediaEngineEx_GetCurrentTime(media_engine); ++ ok(compare_double(time, start, allowed_error), "Unexpected time %lf.\n", time); ++ } ++ ++ Sleep(end * 1000); ++ ++ ret = IMFMediaEngineEx_IsPaused(media_engine); ++ ok(ret, "Unexpected ret %d.\n", ret); ++ time = IMFMediaEngineEx_GetCurrentTime(media_engine); ++ ok(compare_double(time, start, allowed_error) ++ || broken(time >= end), /* Windows 11 21H2 AMD GPU TestBot */ ++ "Unexpected time %lf.\n", time); ++ ++ hr = IMFMediaEngineEx_Play(media_engine); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ res = WaitForSingleObject(notify->seeked_event, timeout); ++ ok(res == WAIT_TIMEOUT, "Unexpected res %#lx.\n", res); ++ ++ /* Media engine is shut down */ ++ hr = IMFMediaEngineEx_Shutdown(media_engine); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ ++ hr = IMFMediaEngineEx_SetCurrentTime(media_engine, start); ++ ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); ++ hr = IMFMediaEngineEx_SetCurrentTimeEx(media_engine, start, MF_MEDIA_ENGINE_SEEK_MODE_NORMAL); ++ ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); ++ ++ IMFMediaEngineEx_Release(media_engine); ++ ++ /* Unseekable bytestreams */ ++ notify = create_seek_notify(); ++ media_engine = create_media_engine_ex(¬ify->IMFMediaEngineNotify_iface, NULL, DXGI_FORMAT_B8G8R8X8_UNORM); ++ IMFMediaEngineNotify_Release(¬ify->IMFMediaEngineNotify_iface); ++ unseekable_stream = create_unseekable_stream(stream); ++ hr = IMFMediaEngineEx_SetSourceFromByteStream(media_engine, unseekable_stream, url); ++ todo_wine_if(hr == MF_E_BYTESTREAM_NOT_SEEKABLE) ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ if (FAILED(hr)) ++ goto done; ++ ++ hr = IMFMediaEngineEx_Play(media_engine); ++ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ++ notify->expected_error = MF_E_INVALIDREQUEST; ++ res = WaitForSingleObject(notify->playing_event, 5000); ++ ok(res == S_OK, "Unexpected res %#lx.\n", res); ++ ++ hr = IMFMediaEngineEx_SetCurrentTime(media_engine, end); ++ ok(hr == S_OK || broken(hr == MF_INVALID_STATE_ERR) /* Win8 */, "Unexpected hr %#lx.\n", hr); ++ if (hr == S_OK) ++ { ++ res = WaitForSingleObject(notify->seeking_event, timeout); ++ ok(res == WAIT_TIMEOUT, "Unexpected res %#lx.\n", res); ++ res = WaitForSingleObject(notify->seeked_event, timeout); ++ ok(res == WAIT_TIMEOUT, "Unexpected res %#lx.\n", res); ++ res = WaitForSingleObject(notify->time_update_event, timeout); ++ ok(!res, "Unexpected res %#lx.\n", res); ++ } ++ ++done: ++ IMFMediaEngineEx_Shutdown(media_engine); ++ IMFMediaEngineEx_Release(media_engine); ++ IMFByteStream_Release(unseekable_stream); ++ SysFreeString(url); ++ IMFByteStream_Release(stream); ++} ++ + START_TEST(mfmediaengine) + { + HRESULT hr; +@@ -2545,6 +2727,7 @@ START_TEST(mfmediaengine) + test_GetDuration(); + test_GetSeekable(); + test_media_extension(); ++ test_SetCurrentTime(); + + IMFMediaEngineClassFactory_Release(factory); + +-- +2.45.1 + diff --git a/patches/wine-gst/0006-AVPro-Video-seeking-support.patch b/patches/wine-gst/0006-AVPro-Video-seeking-support.patch new file mode 100644 index 000000000..a8018e81c --- /dev/null +++ b/patches/wine-gst/0006-AVPro-Video-seeking-support.patch @@ -0,0 +1,22 @@ +From 2a58c6aa882c55eff024396293f2e1f20cd7be06 Mon Sep 17 00:00:00 2001 +From: Torge Matthies +Date: Wed, 10 Apr 2024 18:57:59 +0200 +Subject: [PATCH 06/41] === AVPro Video seeking support === + +--- + MAINTAINERS | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 59873f6804c..ab42dff2884 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -436,3 +436,5 @@ P: Zebediah Figura + P: Paul Gofman + P: Erich E. Hoover + W: https://wine-staging.com/ ++ ++seek +-- +2.45.1 + diff --git a/patches/wine-gst/0001-mf-session-Avoid-leaking-samples-in-transform_node_d.patch b/patches/wine-gst/0007-mf-session-Avoid-leaking-samples-in-transform_node_d.patch similarity index 88% rename from patches/wine-gst/0001-mf-session-Avoid-leaking-samples-in-transform_node_d.patch rename to patches/wine-gst/0007-mf-session-Avoid-leaking-samples-in-transform_node_d.patch index ae0c3b085..7dea208c9 100644 --- a/patches/wine-gst/0001-mf-session-Avoid-leaking-samples-in-transform_node_d.patch +++ b/patches/wine-gst/0007-mf-session-Avoid-leaking-samples-in-transform_node_d.patch @@ -1,7 +1,7 @@ -From 0b86b47fca9d02cc5d3dffcd0023c98ed80323cc Mon Sep 17 00:00:00 2001 +From 9e0aed7b02d2a239662534972fe6db833cb80217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Wed, 13 Mar 2024 10:27:26 +0100 -Subject: [PATCH 01/32] mf/session: Avoid leaking samples in +Subject: [PATCH 07/41] mf/session: Avoid leaking samples in transform_node_deliver_samples. --- diff --git a/patches/wine-gst/0002-Memory-leak-fixes.patch b/patches/wine-gst/0008-Memory-leak-fixes.patch similarity index 77% rename from patches/wine-gst/0002-Memory-leak-fixes.patch rename to patches/wine-gst/0008-Memory-leak-fixes.patch index c1ec404f1..3c02d0441 100644 --- a/patches/wine-gst/0002-Memory-leak-fixes.patch +++ b/patches/wine-gst/0008-Memory-leak-fixes.patch @@ -1,7 +1,7 @@ -From 41a4cb545f26bf07ff595c1bf01b229a97c0efdd Mon Sep 17 00:00:00 2001 +From 0cbe4e45f809b24094c5150468f72bffa2284139 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 10 Apr 2024 18:59:43 +0200 -Subject: [PATCH 02/32] === Memory leak fixes === +Subject: [PATCH 08/41] === Memory leak fixes === --- MAINTAINERS | 1 + diff --git a/patches/wine-gst/0003-winegstreamer-Connect-autoplug-continue-and-deep-ele.patch b/patches/wine-gst/0009-winegstreamer-Connect-autoplug-continue-and-deep-ele.patch similarity index 83% rename from patches/wine-gst/0003-winegstreamer-Connect-autoplug-continue-and-deep-ele.patch rename to patches/wine-gst/0009-winegstreamer-Connect-autoplug-continue-and-deep-ele.patch index 352b0266c..8daf59132 100644 --- a/patches/wine-gst/0003-winegstreamer-Connect-autoplug-continue-and-deep-ele.patch +++ b/patches/wine-gst/0009-winegstreamer-Connect-autoplug-continue-and-deep-ele.patch @@ -1,7 +1,7 @@ -From 305a6ebecb05ed12ac3707407b9be4c95d8ad7d4 Mon Sep 17 00:00:00 2001 +From 14926f4d956adcc8b575c3cf71c946c762442781 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Sun, 31 Mar 2024 15:49:33 +0200 -Subject: [PATCH 03/32] winegstreamer: Connect autoplug-continue and +Subject: [PATCH 09/41] winegstreamer: Connect autoplug-continue and deep-element-added callbacks to uridecodebin-based parsers too. --- @@ -9,10 +9,10 @@ Subject: [PATCH 03/32] winegstreamer: Connect autoplug-continue and 1 file changed, 2 insertions(+) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 2d00f4247e0..cf3b07a3693 100644 +index 6a7fd6d1c71..48a1d658232 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c -@@ -2076,9 +2076,11 @@ static BOOL uridecodebin_parser_init_gst(struct wg_parser *parser) +@@ -2085,9 +2085,11 @@ static BOOL uridecodebin_parser_init_gst(struct wg_parser *parser) g_object_set(parser->decodebin, "uri", parser->uri, NULL); g_signal_connect(element, "pad-added", G_CALLBACK(pad_added_cb), parser); g_signal_connect(element, "pad-removed", G_CALLBACK(pad_removed_cb), parser); diff --git a/patches/wine-gst/0004-winegstreamer-Do-not-create-a-read-thread-for-uridec.patch b/patches/wine-gst/0010-winegstreamer-Do-not-create-a-read-thread-for-uridec.patch similarity index 91% rename from patches/wine-gst/0004-winegstreamer-Do-not-create-a-read-thread-for-uridec.patch rename to patches/wine-gst/0010-winegstreamer-Do-not-create-a-read-thread-for-uridec.patch index 96bbf404d..b00a48a9b 100644 --- a/patches/wine-gst/0004-winegstreamer-Do-not-create-a-read-thread-for-uridec.patch +++ b/patches/wine-gst/0010-winegstreamer-Do-not-create-a-read-thread-for-uridec.patch @@ -1,7 +1,7 @@ -From eb995b90c308d48cd152eeb25b9941f542c7727c Mon Sep 17 00:00:00 2001 +From 89df175af3f4b81fc2d9400cc68ec63c31045582 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Mon, 25 Mar 2024 09:19:18 +0100 -Subject: [PATCH 04/32] winegstreamer: Do not create a read thread for +Subject: [PATCH 10/41] winegstreamer: Do not create a read thread for uridecodebin-based media sources. --- diff --git a/patches/wine-gst/0005-winegstreamer-Ignore-an-assert-in-wg_parser.patch b/patches/wine-gst/0011-winegstreamer-Ignore-an-assert-in-wg_parser.patch similarity index 87% rename from patches/wine-gst/0005-winegstreamer-Ignore-an-assert-in-wg_parser.patch rename to patches/wine-gst/0011-winegstreamer-Ignore-an-assert-in-wg_parser.patch index dfa273a88..ed4ba7d1d 100644 --- a/patches/wine-gst/0005-winegstreamer-Ignore-an-assert-in-wg_parser.patch +++ b/patches/wine-gst/0011-winegstreamer-Ignore-an-assert-in-wg_parser.patch @@ -1,7 +1,7 @@ -From c407df91165ac40aa477110447e25cfc265283bb Mon Sep 17 00:00:00 2001 +From c2dbbfaba56c247e455bd04e938baac9963f9e87 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Tue, 19 Mar 2024 04:06:37 +0100 -Subject: [PATCH 05/32] winegstreamer: Ignore an assert in wg_parser. +Subject: [PATCH 11/41] winegstreamer: Ignore an assert in wg_parser. This gets hit when a wg_parser receives GST_EVENT_FLUSH_START between the wg_parser_stream_get_buffer function return and the wg_parser_stream_release_buffer call. In this case the NULL buffer can be ignored, it does no harm and there @@ -11,7 +11,7 @@ is no memory leak from this. 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index cf3b07a3693..934e7b2fe26 100644 +index 48a1d658232..60d6d2a669e 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -409,11 +409,12 @@ static NTSTATUS wg_parser_stream_release_buffer(void *args) diff --git a/patches/wine-gst/0006-winegstreamer-Fixate-caps-in-autoplug_continue_cb.patch b/patches/wine-gst/0012-winegstreamer-Fixate-caps-in-autoplug_continue_cb.patch similarity index 81% rename from patches/wine-gst/0006-winegstreamer-Fixate-caps-in-autoplug_continue_cb.patch rename to patches/wine-gst/0012-winegstreamer-Fixate-caps-in-autoplug_continue_cb.patch index 82971ce5e..ab8c173f8 100644 --- a/patches/wine-gst/0006-winegstreamer-Fixate-caps-in-autoplug_continue_cb.patch +++ b/patches/wine-gst/0012-winegstreamer-Fixate-caps-in-autoplug_continue_cb.patch @@ -1,7 +1,7 @@ -From 58dffbf17b6704443b1cbed42f09a39d330ffa11 Mon Sep 17 00:00:00 2001 +From 6a57daa8e3493ba35ffc7fc58f9522a332ee859c Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Tue, 19 Mar 2024 10:19:09 +0100 -Subject: [PATCH 06/32] winegstreamer: Fixate caps in autoplug_continue_cb. +Subject: [PATCH 12/41] winegstreamer: Fixate caps in autoplug_continue_cb. Not strictly necessary but avoids an assert in gstreamer code. --- @@ -9,7 +9,7 @@ Not strictly necessary but avoids an assert in gstreamer code. 1 file changed, 2 insertions(+) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 934e7b2fe26..fe846e66324 100644 +index 60d6d2a669e..1ff4da1971c 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -527,7 +527,9 @@ static gboolean autoplug_continue_cb(GstElement * decodebin, GstPad *pad, GstCap diff --git a/patches/wine-gst/0007-winegstreamer-Make-wg_parser-report-the-exact-suppor.patch b/patches/wine-gst/0013-winegstreamer-Make-wg_parser-report-the-exact-suppor.patch similarity index 94% rename from patches/wine-gst/0007-winegstreamer-Make-wg_parser-report-the-exact-suppor.patch rename to patches/wine-gst/0013-winegstreamer-Make-wg_parser-report-the-exact-suppor.patch index 9d01f3846..c1e29b6d9 100644 --- a/patches/wine-gst/0007-winegstreamer-Make-wg_parser-report-the-exact-suppor.patch +++ b/patches/wine-gst/0013-winegstreamer-Make-wg_parser-report-the-exact-suppor.patch @@ -1,7 +1,7 @@ -From dcab8c30f0082381bf0490eccb19a09456070196 Mon Sep 17 00:00:00 2001 +From c3a3416a1ba8b7840501c97bb8b13a13a74f9e78 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Tue, 20 Feb 2024 23:17:28 +0100 -Subject: [PATCH 07/32] winegstreamer: Make wg_parser report the exact +Subject: [PATCH 13/41] winegstreamer: Make wg_parser report the exact supported formats to gstreamer instead of just ANY. --- @@ -9,7 +9,7 @@ Subject: [PATCH 07/32] winegstreamer: Make wg_parser report the exact 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index fe846e66324..b697dae026d 100644 +index 1ff4da1971c..089d659e50d 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -835,6 +835,43 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu diff --git a/patches/wine-gst/0008-winegstreamer-Add-more-RTSP-based-URI-schemes-to-GSt.patch b/patches/wine-gst/0014-winegstreamer-Add-more-RTSP-based-URI-schemes-to-GSt.patch similarity index 94% rename from patches/wine-gst/0008-winegstreamer-Add-more-RTSP-based-URI-schemes-to-GSt.patch rename to patches/wine-gst/0014-winegstreamer-Add-more-RTSP-based-URI-schemes-to-GSt.patch index 1426cc6e3..40eb2174a 100644 --- a/patches/wine-gst/0008-winegstreamer-Add-more-RTSP-based-URI-schemes-to-GSt.patch +++ b/patches/wine-gst/0014-winegstreamer-Add-more-RTSP-based-URI-schemes-to-GSt.patch @@ -1,7 +1,7 @@ -From af400284a4e0be27310fbb5eb3d6956ec27e09d9 Mon Sep 17 00:00:00 2001 +From 3d28b144c1d982fdc9d1e108b9701783f909ea11 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 31 Jan 2024 17:42:54 +0100 -Subject: [PATCH 08/32] winegstreamer: Add more RTSP-based URI schemes to +Subject: [PATCH 14/41] winegstreamer: Add more RTSP-based URI schemes to GStreamer scheme handler. --- diff --git a/patches/wine-gst/0009-winegstreamer-Fixate-caps-in-the-pad-added-callback.patch b/patches/wine-gst/0015-winegstreamer-Fixate-caps-in-the-pad-added-callback.patch similarity index 88% rename from patches/wine-gst/0009-winegstreamer-Fixate-caps-in-the-pad-added-callback.patch rename to patches/wine-gst/0015-winegstreamer-Fixate-caps-in-the-pad-added-callback.patch index 25daaf5d5..a1b05677e 100644 --- a/patches/wine-gst/0009-winegstreamer-Fixate-caps-in-the-pad-added-callback.patch +++ b/patches/wine-gst/0015-winegstreamer-Fixate-caps-in-the-pad-added-callback.patch @@ -1,7 +1,7 @@ -From 73a2026f5cfd19d3ec6281fe532047d76c4abf86 Mon Sep 17 00:00:00 2001 +From 90ba1fc1cd1e6eacdc9652772f3cb6268a85f9a8 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Mon, 22 Apr 2024 11:44:37 +0200 -Subject: [PATCH 09/32] winegstreamer: Fixate caps in the pad-added callback. +Subject: [PATCH 15/41] winegstreamer: Fixate caps in the pad-added callback. Pad caps might not be fixed caps, and non-fixed caps can't be transformed to a wg_format. --- @@ -9,7 +9,7 @@ Pad caps might not be fixed caps, and non-fixed caps can't be transformed to a w 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index b697dae026d..7216b640ca1 100644 +index 089d659e50d..3a39a754b81 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1209,7 +1209,7 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user) diff --git a/patches/wine-gst/0010-winegstreamer-Mark-wg_parser-container-bin-as-stream.patch b/patches/wine-gst/0016-winegstreamer-Mark-wg_parser-container-bin-as-stream.patch similarity index 74% rename from patches/wine-gst/0010-winegstreamer-Mark-wg_parser-container-bin-as-stream.patch rename to patches/wine-gst/0016-winegstreamer-Mark-wg_parser-container-bin-as-stream.patch index 0fddfd4cb..97a8dadb7 100644 --- a/patches/wine-gst/0010-winegstreamer-Mark-wg_parser-container-bin-as-stream.patch +++ b/patches/wine-gst/0016-winegstreamer-Mark-wg_parser-container-bin-as-stream.patch @@ -1,7 +1,7 @@ -From 1c75e04f488748f2cdcdadb9f5f2d11346382bc4 Mon Sep 17 00:00:00 2001 +From 6d896fadfbc36ebd6a8f6b18231895feba63f344 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Mon, 22 Apr 2024 11:43:45 +0200 -Subject: [PATCH 10/32] winegstreamer: Mark wg_parser container bin as +Subject: [PATCH 16/41] winegstreamer: Mark wg_parser container bin as streams-aware. Mirroring wg_source. @@ -10,10 +10,10 @@ Mirroring wg_source. 1 file changed, 1 insertion(+) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 7216b640ca1..94df2db1509 100644 +index 3a39a754b81..b89a25fd9ef 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c -@@ -1864,6 +1864,7 @@ static NTSTATUS wg_parser_connect(void *args) +@@ -1873,6 +1873,7 @@ static NTSTATUS wg_parser_connect(void *args) } parser->container = gst_bin_new(NULL); diff --git a/patches/wine-gst/0011-winegstreamer-Set-a-clock-for-the-wg_parser-pipeline.patch b/patches/wine-gst/0017-winegstreamer-Set-a-clock-for-the-wg_parser-pipeline.patch similarity index 78% rename from patches/wine-gst/0011-winegstreamer-Set-a-clock-for-the-wg_parser-pipeline.patch rename to patches/wine-gst/0017-winegstreamer-Set-a-clock-for-the-wg_parser-pipeline.patch index 779d64b52..58383ab4f 100644 --- a/patches/wine-gst/0011-winegstreamer-Set-a-clock-for-the-wg_parser-pipeline.patch +++ b/patches/wine-gst/0017-winegstreamer-Set-a-clock-for-the-wg_parser-pipeline.patch @@ -1,7 +1,7 @@ -From 8cb0b6b9749dbac3818032f29689b4d57d88bb2f Mon Sep 17 00:00:00 2001 +From 123b678be6b58e024ecd183cb73b7f7e5c77f913 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 31 Jan 2024 17:42:55 +0100 -Subject: [PATCH 11/32] winegstreamer: Set a clock for the wg_parser pipeline. +Subject: [PATCH 17/41] winegstreamer: Set a clock for the wg_parser pipeline. Some elements under uridecodebin (e.g. the RTSP demuxer) require a valid clock to function properly. GstPipeline does this so let's do this too. @@ -10,10 +10,10 @@ GstPipeline does this so let's do this too. 1 file changed, 2 insertions(+) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 94df2db1509..fa59a7c844f 100644 +index b89a25fd9ef..cd193b8f2af 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c -@@ -1876,6 +1876,8 @@ static NTSTATUS wg_parser_connect(void *args) +@@ -1885,6 +1885,8 @@ static NTSTATUS wg_parser_connect(void *args) gst_pad_set_event_function(parser->my_src, src_event_cb); gst_pad_set_element_private(parser->my_src, parser); diff --git a/patches/wine-gst/0012-winegstreamer-Set-base-time-on-wg_parser-bin-while-c.patch b/patches/wine-gst/0018-winegstreamer-Set-base-time-on-wg_parser-bin-while-c.patch similarity index 78% rename from patches/wine-gst/0012-winegstreamer-Set-base-time-on-wg_parser-bin-while-c.patch rename to patches/wine-gst/0018-winegstreamer-Set-base-time-on-wg_parser-bin-while-c.patch index 4f6f2366d..42315456c 100644 --- a/patches/wine-gst/0012-winegstreamer-Set-base-time-on-wg_parser-bin-while-c.patch +++ b/patches/wine-gst/0018-winegstreamer-Set-base-time-on-wg_parser-bin-while-c.patch @@ -1,7 +1,7 @@ -From 1ba3b50a49c2f5c4c61e78f2d4452dbecc8af100 Mon Sep 17 00:00:00 2001 +From 90668d64f7fd19e763fc5f88a6c5ce3c4b2a005f Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 31 Jan 2024 17:42:55 +0100 -Subject: [PATCH 12/32] winegstreamer: Set base time on wg_parser bin while +Subject: [PATCH 18/41] winegstreamer: Set base time on wg_parser bin while connecting. --- @@ -9,10 +9,10 @@ Subject: [PATCH 12/32] winegstreamer: Set base time on wg_parser bin while 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index fa59a7c844f..0ff3c8673a8 100644 +index cd193b8f2af..fdbce6b5f25 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c -@@ -1840,6 +1840,7 @@ static NTSTATUS wg_parser_connect(void *args) +@@ -1849,6 +1849,7 @@ static NTSTATUS wg_parser_connect(void *args) const struct wg_parser_connect_params *params = args; struct wg_parser *parser = get_parser(params->parser); const WCHAR *uri = params->uri; @@ -20,7 +20,7 @@ index fa59a7c844f..0ff3c8673a8 100644 unsigned int i; int ret; -@@ -1876,7 +1877,8 @@ static NTSTATUS wg_parser_connect(void *args) +@@ -1885,7 +1886,8 @@ static NTSTATUS wg_parser_connect(void *args) gst_pad_set_event_function(parser->my_src, src_event_cb); gst_pad_set_element_private(parser->my_src, parser); @@ -30,7 +30,7 @@ index fa59a7c844f..0ff3c8673a8 100644 parser->start_offset = parser->next_offset = parser->stop_offset = 0; parser->next_pull_offset = 0; -@@ -1885,6 +1887,7 @@ static NTSTATUS wg_parser_connect(void *args) +@@ -1894,6 +1896,7 @@ static NTSTATUS wg_parser_connect(void *args) if (!parser->init_gst(parser)) goto out; diff --git a/patches/wine-gst/0013-winegstreamer-Put-pipeline-into-PLAYING-state-before.patch b/patches/wine-gst/0019-winegstreamer-Put-pipeline-into-PLAYING-state-before.patch similarity index 80% rename from patches/wine-gst/0013-winegstreamer-Put-pipeline-into-PLAYING-state-before.patch rename to patches/wine-gst/0019-winegstreamer-Put-pipeline-into-PLAYING-state-before.patch index 8c0bfc0d6..3dfd6ddac 100644 --- a/patches/wine-gst/0013-winegstreamer-Put-pipeline-into-PLAYING-state-before.patch +++ b/patches/wine-gst/0019-winegstreamer-Put-pipeline-into-PLAYING-state-before.patch @@ -1,7 +1,7 @@ -From 66215897b86e34336e7308121f61fda9b684be20 Mon Sep 17 00:00:00 2001 +From 1b6f98bdd43d4aecec34f592a5274a23861a3247 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 31 Jan 2024 17:42:55 +0100 -Subject: [PATCH 13/32] winegstreamer: Put pipeline into PLAYING state before +Subject: [PATCH 19/41] winegstreamer: Put pipeline into PLAYING state before waiting for the no-more-pads callback. Some elements (e.g. uridecodebin with an RTSP URI) won't send no-more-pads in READY/PAUSED state. @@ -10,10 +10,10 @@ Some elements (e.g. uridecodebin with an RTSP URI) won't send no-more-pads in RE 1 file changed, 7 insertions(+) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 0ff3c8673a8..2df4bba525d 100644 +index fdbce6b5f25..83786a4aa4c 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c -@@ -1905,6 +1905,13 @@ static NTSTATUS wg_parser_connect(void *args) +@@ -1914,6 +1914,13 @@ static NTSTATUS wg_parser_connect(void *args) pthread_mutex_lock(&parser->mutex); diff --git a/patches/wine-gst/0014-winegstreamer-Don-t-only-accept-segment-events-when-.patch b/patches/wine-gst/0020-winegstreamer-Don-t-only-accept-segment-events-when-.patch similarity index 91% rename from patches/wine-gst/0014-winegstreamer-Don-t-only-accept-segment-events-when-.patch rename to patches/wine-gst/0020-winegstreamer-Don-t-only-accept-segment-events-when-.patch index 6981dcaad..1cc1e4f11 100644 --- a/patches/wine-gst/0014-winegstreamer-Don-t-only-accept-segment-events-when-.patch +++ b/patches/wine-gst/0020-winegstreamer-Don-t-only-accept-segment-events-when-.patch @@ -1,7 +1,7 @@ -From cd22b29affc4004a8e6258b7d195bbf2b47821dd Mon Sep 17 00:00:00 2001 +From 6a485e675b799bbaa0632559dca733524d77ed87 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Tue, 23 Apr 2024 19:30:17 +0200 -Subject: [PATCH 14/32] winegstreamer: Don't only accept segment events when +Subject: [PATCH 20/41] winegstreamer: Don't only accept segment events when streams are enabled. I don't know why this was done previously but this just creates a race condition, with no to me apparent benefit. @@ -10,7 +10,7 @@ I don't know why this was done previously but this just creates a race condition 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 2df4bba525d..a6c850d7a4c 100644 +index 83786a4aa4c..3eb4134b931 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -683,24 +683,20 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) diff --git a/patches/wine-gst/0015-winegstreamer-Convert-buffer-presentation-timestamps.patch b/patches/wine-gst/0021-winegstreamer-Convert-buffer-presentation-timestamps.patch similarity index 94% rename from patches/wine-gst/0015-winegstreamer-Convert-buffer-presentation-timestamps.patch rename to patches/wine-gst/0021-winegstreamer-Convert-buffer-presentation-timestamps.patch index 2b5ebdd0a..de1a16761 100644 --- a/patches/wine-gst/0015-winegstreamer-Convert-buffer-presentation-timestamps.patch +++ b/patches/wine-gst/0021-winegstreamer-Convert-buffer-presentation-timestamps.patch @@ -1,7 +1,7 @@ -From e4fb9bceb21eea57decb660e9a8065524cf0ff71 Mon Sep 17 00:00:00 2001 +From ae9d92823f7ee45e83f70c932139c750a5cc8525 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 31 Jan 2024 17:42:55 +0100 -Subject: [PATCH 15/32] winegstreamer: Convert buffer presentation timestamps +Subject: [PATCH 21/41] winegstreamer: Convert buffer presentation timestamps into running time. --- @@ -9,7 +9,7 @@ Subject: [PATCH 15/32] winegstreamer: Convert buffer presentation timestamps 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index a6c850d7a4c..740fb1cc904 100644 +index 3eb4134b931..e6170b96cb9 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -306,6 +306,18 @@ static GstBuffer *wait_parser_stream_buffer(struct wg_parser *parser, struct wg_ diff --git a/patches/wine-gst/0016-winegstreamer-Adjust-buffer-timestamps-after-seek.patch b/patches/wine-gst/0022-winegstreamer-Adjust-buffer-timestamps-after-seek.patch similarity index 92% rename from patches/wine-gst/0016-winegstreamer-Adjust-buffer-timestamps-after-seek.patch rename to patches/wine-gst/0022-winegstreamer-Adjust-buffer-timestamps-after-seek.patch index 2f860c88a..24b0390a7 100644 --- a/patches/wine-gst/0016-winegstreamer-Adjust-buffer-timestamps-after-seek.patch +++ b/patches/wine-gst/0022-winegstreamer-Adjust-buffer-timestamps-after-seek.patch @@ -1,14 +1,14 @@ -From 6c0dfd685282577de950ba8df95904537750f82a Mon Sep 17 00:00:00 2001 +From 13b6c041294829539c59b2958fb2766d06d2112a Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Tue, 19 Mar 2024 05:11:11 +0100 -Subject: [PATCH 16/32] winegstreamer: Adjust buffer timestamps after seek. +Subject: [PATCH 22/41] winegstreamer: Adjust buffer timestamps after seek. --- dlls/winegstreamer/wg_parser.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 740fb1cc904..ab8844ce531 100644 +index e6170b96cb9..c7515b55080 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -132,6 +132,8 @@ struct wg_parser_stream diff --git a/patches/wine-gst/0017-winegstreamer-Reorder-parser-initialization-code-a-b.patch b/patches/wine-gst/0023-winegstreamer-Reorder-parser-initialization-code-a-b.patch similarity index 87% rename from patches/wine-gst/0017-winegstreamer-Reorder-parser-initialization-code-a-b.patch rename to patches/wine-gst/0023-winegstreamer-Reorder-parser-initialization-code-a-b.patch index 7d1860581..7fb3f4493 100644 --- a/patches/wine-gst/0017-winegstreamer-Reorder-parser-initialization-code-a-b.patch +++ b/patches/wine-gst/0023-winegstreamer-Reorder-parser-initialization-code-a-b.patch @@ -1,7 +1,7 @@ -From e31bc31f0346b9577d3794e2ac25bf81997869ce Mon Sep 17 00:00:00 2001 +From 2f54eda34559e4577506e78ea8cd80315db8fe3c Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 31 Jan 2024 17:42:55 +0100 -Subject: [PATCH 17/32] winegstreamer: Reorder parser initialization code a bit +Subject: [PATCH 23/41] winegstreamer: Reorder parser initialization code a bit to prevent race conditions. --- @@ -9,10 +9,10 @@ Subject: [PATCH 17/32] winegstreamer: Reorder parser initialization code a bit 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index ab8844ce531..3f57ec74131 100644 +index c7515b55080..1b6c2432244 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c -@@ -2119,7 +2119,10 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser) +@@ -2128,7 +2128,10 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser) gst_bin_add(GST_BIN(parser->container), element); parser->decodebin = element; @@ -24,7 +24,7 @@ index ab8844ce531..3f57ec74131 100644 g_signal_connect(element, "pad-added", G_CALLBACK(pad_added_cb), parser); g_signal_connect(element, "pad-removed", G_CALLBACK(pad_removed_cb), parser); g_signal_connect(element, "autoplug-continue", G_CALLBACK(autoplug_continue_cb), parser); -@@ -2127,10 +2130,7 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser) +@@ -2136,10 +2139,7 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser) g_signal_connect(element, "autoplug-sort", G_CALLBACK(autoplug_sort_cb), parser); g_signal_connect(element, "no-more-pads", G_CALLBACK(no_more_pads_cb), parser); g_signal_connect(element, "deep-element-added", G_CALLBACK(deep_element_added_cb), parser); @@ -36,7 +36,7 @@ index ab8844ce531..3f57ec74131 100644 if (!link_src_to_element(parser->my_src, element)) return FALSE; -@@ -2148,7 +2148,10 @@ static BOOL uridecodebin_parser_init_gst(struct wg_parser *parser) +@@ -2157,7 +2157,10 @@ static BOOL uridecodebin_parser_init_gst(struct wg_parser *parser) gst_bin_add(GST_BIN(parser->container), element); parser->decodebin = element; @@ -48,7 +48,7 @@ index ab8844ce531..3f57ec74131 100644 g_signal_connect(element, "pad-added", G_CALLBACK(pad_added_cb), parser); g_signal_connect(element, "pad-removed", G_CALLBACK(pad_removed_cb), parser); g_signal_connect(element, "autoplug-continue", G_CALLBACK(autoplug_continue_cb), parser); -@@ -2156,10 +2159,7 @@ static BOOL uridecodebin_parser_init_gst(struct wg_parser *parser) +@@ -2165,10 +2168,7 @@ static BOOL uridecodebin_parser_init_gst(struct wg_parser *parser) g_signal_connect(element, "autoplug-sort", G_CALLBACK(autoplug_sort_cb), parser); g_signal_connect(element, "no-more-pads", G_CALLBACK(no_more_pads_cb), parser); g_signal_connect(element, "deep-element-added", G_CALLBACK(deep_element_added_cb), parser); @@ -60,7 +60,7 @@ index ab8844ce531..3f57ec74131 100644 return TRUE; } -@@ -2173,14 +2173,14 @@ static BOOL avi_parser_init_gst(struct wg_parser *parser) +@@ -2182,14 +2182,14 @@ static BOOL avi_parser_init_gst(struct wg_parser *parser) gst_bin_add(GST_BIN(parser->container), element); diff --git a/patches/wine-gst/0018-winegstreamer-Do-away-with-the-per-stream-condvars-a.patch b/patches/wine-gst/0024-winegstreamer-Do-away-with-the-per-stream-condvars-a.patch similarity index 94% rename from patches/wine-gst/0018-winegstreamer-Do-away-with-the-per-stream-condvars-a.patch rename to patches/wine-gst/0024-winegstreamer-Do-away-with-the-per-stream-condvars-a.patch index 891f072a1..5ccf1e8b2 100644 --- a/patches/wine-gst/0018-winegstreamer-Do-away-with-the-per-stream-condvars-a.patch +++ b/patches/wine-gst/0024-winegstreamer-Do-away-with-the-per-stream-condvars-a.patch @@ -1,7 +1,7 @@ -From 577c68c9f2a47085a6714dee102e4b960a7ae324 Mon Sep 17 00:00:00 2001 +From e2330ed45bf01400c95f081273e2863dace1a981 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 31 Jan 2024 17:42:54 +0100 -Subject: [PATCH 18/32] winegstreamer: Do away with the per-stream condvars and +Subject: [PATCH 24/41] winegstreamer: Do away with the per-stream condvars and use one parser-wide condvar instead. --- @@ -9,7 +9,7 @@ Subject: [PATCH 18/32] winegstreamer: Do away with the per-stream condvars and 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 3f57ec74131..5421c821a30 100644 +index 1b6c2432244..7fe5074dd7e 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -90,6 +90,7 @@ struct wg_parser @@ -112,7 +112,7 @@ index 3f57ec74131..5421c821a30 100644 for (i = 0; i < ARRAY_SIZE(stream->tags); ++i) { if (stream->tags[i]) -@@ -2070,10 +2065,8 @@ static NTSTATUS wg_parser_disconnect(void *args) +@@ -2079,10 +2074,8 @@ static NTSTATUS wg_parser_disconnect(void *args) /* Unblock all of our streams. */ pthread_mutex_lock(&parser->mutex); for (i = 0; i < parser->stream_count; ++i) @@ -124,7 +124,7 @@ index 3f57ec74131..5421c821a30 100644 pthread_mutex_unlock(&parser->mutex); gst_element_set_state(parser->container, GST_STATE_NULL); -@@ -2249,6 +2242,7 @@ static NTSTATUS wg_parser_create(void *args) +@@ -2258,6 +2251,7 @@ static NTSTATUS wg_parser_create(void *args) pthread_cond_init(&parser->init_cond, NULL); pthread_cond_init(&parser->read_cond, NULL); pthread_cond_init(&parser->read_done_cond, NULL); diff --git a/patches/wine-gst/0019-winegstreamer-Use-pthread_cond_broadcast-instead-of-.patch b/patches/wine-gst/0025-winegstreamer-Use-pthread_cond_broadcast-instead-of-.patch similarity index 92% rename from patches/wine-gst/0019-winegstreamer-Use-pthread_cond_broadcast-instead-of-.patch rename to patches/wine-gst/0025-winegstreamer-Use-pthread_cond_broadcast-instead-of-.patch index 733561d6c..d0e232391 100644 --- a/patches/wine-gst/0019-winegstreamer-Use-pthread_cond_broadcast-instead-of-.patch +++ b/patches/wine-gst/0025-winegstreamer-Use-pthread_cond_broadcast-instead-of-.patch @@ -1,7 +1,7 @@ -From 3f04d2329715f626653cfa26c07d348cc0ceb9e4 Mon Sep 17 00:00:00 2001 +From ba44594c4411d62c5f0de90f56786801d9d69407 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Mon, 18 Mar 2024 10:18:07 +0100 -Subject: [PATCH 19/32] winegstreamer: Use pthread_cond_broadcast instead of +Subject: [PATCH 25/41] winegstreamer: Use pthread_cond_broadcast instead of pthread_cond_signal for stream_event_cond. --- @@ -9,7 +9,7 @@ Subject: [PATCH 19/32] winegstreamer: Use pthread_cond_broadcast instead of 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 5421c821a30..1cee2698b4f 100644 +index 7fe5074dd7e..88ffdbfe047 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -290,7 +290,7 @@ static NTSTATUS wg_parser_stream_disable(void *args) @@ -57,7 +57,7 @@ index 5421c821a30..1cee2698b4f 100644 /* The chain callback is given a reference to the buffer. Transfer that * reference to the stream object, which will release it in -@@ -2066,7 +2066,7 @@ static NTSTATUS wg_parser_disconnect(void *args) +@@ -2075,7 +2075,7 @@ static NTSTATUS wg_parser_disconnect(void *args) pthread_mutex_lock(&parser->mutex); for (i = 0; i < parser->stream_count; ++i) parser->streams[i]->flushing = true; diff --git a/patches/wine-gst/0020-winegstreamer-Do-not-fail-caps-negotiation-when-ther.patch b/patches/wine-gst/0026-winegstreamer-Do-not-fail-caps-negotiation-when-ther.patch similarity index 96% rename from patches/wine-gst/0020-winegstreamer-Do-not-fail-caps-negotiation-when-ther.patch rename to patches/wine-gst/0026-winegstreamer-Do-not-fail-caps-negotiation-when-ther.patch index 9ebfa63f8..f5a3b51b6 100644 --- a/patches/wine-gst/0020-winegstreamer-Do-not-fail-caps-negotiation-when-ther.patch +++ b/patches/wine-gst/0026-winegstreamer-Do-not-fail-caps-negotiation-when-ther.patch @@ -1,7 +1,7 @@ -From 7e0ce2f02b44eedca362652d8f4b1bf38be6198c Mon Sep 17 00:00:00 2001 +From a60b73ed619462e42cd70dd545816e5d08f05deb Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Tue, 19 Mar 2024 10:09:59 +0100 -Subject: [PATCH 20/32] winegstreamer: Do not fail caps negotiation when +Subject: [PATCH 26/41] winegstreamer: Do not fail caps negotiation when there's a concurrent reconfigure. If wg_parser_stream_enable is called between the time our sink's GST_QUERY_CAPS returns and the time our sink gets the @@ -18,7 +18,7 @@ Also try to omit the reconfigure event in some cases. 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 1cee2698b4f..b11e00d0908 100644 +index 88ffdbfe047..ca0a8c38890 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -121,7 +121,7 @@ struct wg_parser_stream @@ -150,7 +150,7 @@ index 1cee2698b4f..b11e00d0908 100644 { pthread_mutex_unlock(&parser->mutex); gst_query_set_accept_caps_result(query, TRUE); -@@ -1636,6 +1691,7 @@ static GstBusSyncReply bus_handler_cb(GstBus *bus, GstMessage *msg, gpointer use +@@ -1645,6 +1700,7 @@ static GstBusSyncReply bus_handler_cb(GstBus *bus, GstMessage *msg, gpointer use parser->error = true; pthread_mutex_unlock(&parser->mutex); pthread_cond_signal(&parser->init_cond); @@ -158,7 +158,7 @@ index 1cee2698b4f..b11e00d0908 100644 break; case GST_MESSAGE_WARNING: -@@ -1666,6 +1722,7 @@ static GstBusSyncReply bus_handler_cb(GstBus *bus, GstMessage *msg, gpointer use +@@ -1675,6 +1731,7 @@ static GstBusSyncReply bus_handler_cb(GstBus *bus, GstMessage *msg, gpointer use GST_WARNING("Autoplugged element failed to initialise, trying again with protonvideoconvert."); parser->error = true; pthread_cond_signal(&parser->init_cond); diff --git a/patches/wine-gst/0021-winegstreamer-Do-not-seek-live-sources.patch b/patches/wine-gst/0027-winegstreamer-Do-not-seek-live-sources.patch similarity index 91% rename from patches/wine-gst/0021-winegstreamer-Do-not-seek-live-sources.patch rename to patches/wine-gst/0027-winegstreamer-Do-not-seek-live-sources.patch index 57dbabadd..4e59ca6f8 100644 --- a/patches/wine-gst/0021-winegstreamer-Do-not-seek-live-sources.patch +++ b/patches/wine-gst/0027-winegstreamer-Do-not-seek-live-sources.patch @@ -1,7 +1,7 @@ -From f1cd3d390d097700d23c8bff83122eb5f494e3f4 Mon Sep 17 00:00:00 2001 +From 8fb4d0063a7ab09dbd1c4ec6c20d091f46e447cb Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Sun, 14 Apr 2024 06:12:55 +0200 -Subject: [PATCH 21/32] winegstreamer: Do not seek live sources. +Subject: [PATCH 27/41] winegstreamer: Do not seek live sources. souphttpsrc seems to break from seeking sometimes: @@ -15,7 +15,7 @@ Seeking a live source doesn't make sense anyway. 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index b11e00d0908..ae6286b8084 100644 +index ca0a8c38890..d4600f8a55e 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -110,6 +110,8 @@ struct wg_parser @@ -55,7 +55,7 @@ index b11e00d0908..ae6286b8084 100644 } static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) -@@ -1956,7 +1965,11 @@ static NTSTATUS wg_parser_connect(void *args) +@@ -1965,7 +1974,11 @@ static NTSTATUS wg_parser_connect(void *args) goto out; gst_element_set_base_time(parser->container, gst_clock_get_time(clock)); @@ -68,7 +68,7 @@ index b11e00d0908..ae6286b8084 100644 ret = gst_element_get_state(parser->container, NULL, NULL, -1); if (ret == GST_STATE_CHANGE_FAILURE) -@@ -1975,7 +1988,11 @@ static NTSTATUS wg_parser_connect(void *args) +@@ -1984,7 +1997,11 @@ static NTSTATUS wg_parser_connect(void *args) if (parser->uri) { diff --git a/patches/wine-gst/0022-winegstreamer-Implement-buffering-events.patch b/patches/wine-gst/0028-winegstreamer-Implement-buffering-events.patch similarity index 95% rename from patches/wine-gst/0022-winegstreamer-Implement-buffering-events.patch rename to patches/wine-gst/0028-winegstreamer-Implement-buffering-events.patch index 5c3433634..da696c9c2 100644 --- a/patches/wine-gst/0022-winegstreamer-Implement-buffering-events.patch +++ b/patches/wine-gst/0028-winegstreamer-Implement-buffering-events.patch @@ -1,7 +1,7 @@ -From dbe8165373d597230643276c9ff1d44af8599060 Mon Sep 17 00:00:00 2001 +From 71459b38382b89260a705eb15693de04cb119658 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 10 Apr 2024 15:11:02 +0200 -Subject: [PATCH 22/32] winegstreamer: Implement buffering events. +Subject: [PATCH 28/41] winegstreamer: Implement buffering events. --- dlls/winegstreamer/gst_private.h | 3 ++ @@ -188,7 +188,7 @@ index fe21a24f6f5..154469a096a 100644 unix_wg_parser_get_stream, diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index ae6286b8084..4e1702893d0 100644 +index d4600f8a55e..7e335e2900d 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -43,6 +43,12 @@ @@ -262,7 +262,7 @@ index ae6286b8084..4e1702893d0 100644 static NTSTATUS wg_parser_stream_get_preferred_format(void *args) { const struct wg_parser_stream_get_preferred_format_params *params = args; -@@ -1755,6 +1805,19 @@ static GstBusSyncReply bus_handler_cb(GstBus *bus, GstMessage *msg, gpointer use +@@ -1764,6 +1814,19 @@ static GstBusSyncReply bus_handler_cb(GstBus *bus, GstMessage *msg, gpointer use break; } @@ -282,7 +282,7 @@ index ae6286b8084..4e1702893d0 100644 default: break; } -@@ -2151,6 +2214,7 @@ static NTSTATUS wg_parser_disconnect(void *args) +@@ -2160,6 +2223,7 @@ static NTSTATUS wg_parser_disconnect(void *args) parser->sink_connected = false; pthread_mutex_unlock(&parser->mutex); pthread_cond_signal(&parser->read_cond); @@ -290,7 +290,7 @@ index ae6286b8084..4e1702893d0 100644 for (i = 0; i < parser->stream_count; ++i) free_stream(parser->streams[i]); -@@ -2364,6 +2428,8 @@ const unixlib_entry_t __wine_unix_call_funcs[] = +@@ -2373,6 +2437,8 @@ const unixlib_entry_t __wine_unix_call_funcs[] = X(wg_parser_get_next_read_offset), X(wg_parser_push_data), @@ -299,7 +299,7 @@ index ae6286b8084..4e1702893d0 100644 X(wg_parser_get_stream_count), X(wg_parser_get_stream), -@@ -2791,6 +2857,8 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = +@@ -2818,6 +2884,8 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = X(wg_parser_get_next_read_offset), X64(wg_parser_push_data), diff --git a/patches/wine-gst/0032-mf-Send-sample-requests-for-unused-space-of-sample-q.patch b/patches/wine-gst/0029-mf-Send-sample-requests-for-unused-space-of-sample-q.patch similarity index 96% rename from patches/wine-gst/0032-mf-Send-sample-requests-for-unused-space-of-sample-q.patch rename to patches/wine-gst/0029-mf-Send-sample-requests-for-unused-space-of-sample-q.patch index 8fa261d1b..f50c57afc 100644 --- a/patches/wine-gst/0032-mf-Send-sample-requests-for-unused-space-of-sample-q.patch +++ b/patches/wine-gst/0029-mf-Send-sample-requests-for-unused-space-of-sample-q.patch @@ -1,7 +1,7 @@ -From 64935c3313adc220e6c7032feffccc9dfd842d98 Mon Sep 17 00:00:00 2001 +From 498c82029aedbd582676b2e9464eee231c88a697 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Tue, 21 May 2024 08:25:47 +0200 -Subject: [PATCH 32/32] mf: Send sample requests for unused space of sample +Subject: [PATCH 29/41] mf: Send sample requests for unused space of sample queue on pause => restart. --- diff --git a/patches/wine-gst/0030-winegstreamer-Add-a-queue-of-buffers-to-wg_parser-to.patch b/patches/wine-gst/0030-winegstreamer-Add-a-queue-of-buffers-to-wg_parser-to.patch new file mode 100644 index 000000000..9b3151d4f --- /dev/null +++ b/patches/wine-gst/0030-winegstreamer-Add-a-queue-of-buffers-to-wg_parser-to.patch @@ -0,0 +1,196 @@ +From e35df678b7966e8074cec36e2bdee2f9ea2779aa Mon Sep 17 00:00:00 2001 +From: Torge Matthies +Date: Mon, 3 Jun 2024 10:57:07 +0200 +Subject: [PATCH 30/41] winegstreamer: Add a queue of buffers to wg_parser to + prevent locking up pipeline. + +Without this, sink_chain_cb could block while one or more other stream didn't have a buffer/sample ready. +If the application then waits for a sample on a stream without one ready, and never receives the sample that is +providing backpressure to the pipeline (by blocking in sink_chain_cb), the pipeline would stay locked up indefinitely. + +Essentially +- Application is waiting for a sample from stream 1 before requesting a sample from stream 2 +- sink_chain_cb is waiting to deliver a sample on stream 2 before unblocking the pipeline, which would allow Gstreamer + to deliver a sample to stream 1 +--- + dlls/winegstreamer/wg_parser.c | 108 ++++++++++++++++++++++++++++++--- + 1 file changed, 101 insertions(+), 7 deletions(-) + +diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c +index 7e335e2900d..fd749572b51 100644 +--- a/dlls/winegstreamer/wg_parser.c ++++ b/dlls/winegstreamer/wg_parser.c +@@ -137,6 +137,12 @@ struct wg_parser_stream + GstBuffer *buffer; + GstMapInfo map_info; + ++ GstBuffer **queued_buffers; ++ size_t num_queued; ++ size_t queue_capacity; ++ ++ GstClockTime latest_buffer_end_pts; ++ + bool flushing, eos, enabled, has_caps, has_tags, has_buffer, no_more_pads; + + uint64_t duration; +@@ -393,6 +399,22 @@ static void release_buffer(struct wg_parser *parser, struct wg_parser_stream *st + stream->buffer = NULL; + } + ++ while (!stream->buffer && stream->num_queued) ++ { ++ GstBuffer *buffer = stream->queued_buffers[0]; ++ ++ memmove(stream->queued_buffers, stream->queued_buffers + 1, (stream->num_queued - 1) * sizeof(buffer)); ++ stream->num_queued -= 1; ++ ++ if (!gst_buffer_map(buffer, &stream->map_info, GST_MAP_READ)) ++ { ++ GST_ERROR("Failed to map buffer."); ++ gst_buffer_unref(buffer); ++ } ++ else ++ stream->buffer = buffer; ++ } ++ + pthread_cond_broadcast(&parser->stream_event_cond); + } + +@@ -816,6 +838,8 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) + + if (stream->enabled) + { ++ size_t i; ++ + stream->flushing = true; + pthread_cond_broadcast(&parser->stream_event_cond); + +@@ -825,6 +849,11 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) + gst_buffer_unref(stream->buffer); + stream->buffer = NULL; + } ++ ++ for (i = 0; i < stream->num_queued; i++) ++ gst_buffer_unref(stream->queued_buffers[i]); ++ stream->num_queued = 0; ++ stream->latest_buffer_end_pts = 0; + } + + pthread_mutex_unlock(&parser->mutex); +@@ -887,10 +916,41 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) + return TRUE; + } + ++static inline bool has_queue_space(struct wg_parser_stream *stream, GstBuffer *buffer) ++{ ++ struct wg_parser *parser = stream->parser; ++ bool missing_buffer = false; ++ size_t i; ++ ++ for (i = 0; i < parser->stream_count; i++) ++ { ++ struct wg_parser_stream *other_stream = parser->streams[i]; ++ if (other_stream == stream) ++ continue; ++ if (!other_stream->buffer) ++ missing_buffer = true; ++ } ++ if (!missing_buffer) ++ return false; ++ ++ for (i = 0; i < parser->stream_count; i++) ++ { ++ struct wg_parser_stream *other_stream = parser->streams[i]; ++ if (other_stream == stream) ++ continue; ++ if (other_stream->latest_buffer_end_pts == 0) ++ return true; ++ if (GST_BUFFER_PTS(buffer) < other_stream->latest_buffer_end_pts) ++ return true; ++ } ++ return false; ++} ++ + static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *buffer) + { + struct wg_parser_stream *stream = gst_pad_get_element_private(pad); + struct wg_parser *parser = stream->parser; ++ GstClockTime end_pts; + + GST_LOG("stream %p, buffer %p.", stream, buffer); + +@@ -913,7 +973,7 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu + /* Allow this buffer to be flushed by GStreamer. We are effectively + * implementing a queue object here. */ + +- while (stream->enabled && !stream->flushing && stream->buffer) ++ while (stream->enabled && !stream->flushing && stream->buffer && !has_queue_space(stream, buffer)) + pthread_cond_wait(&parser->stream_event_cond, &parser->mutex); + + if (!stream->enabled) +@@ -932,15 +992,45 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu + return GST_FLOW_FLUSHING; + } + +- if (!gst_buffer_map(buffer, &stream->map_info, GST_MAP_READ)) ++ if (!stream->buffer) + { +- pthread_mutex_unlock(&parser->mutex); +- GST_ERROR("Failed to map buffer."); +- gst_buffer_unref(buffer); +- return GST_FLOW_ERROR; ++ if (!gst_buffer_map(buffer, &stream->map_info, GST_MAP_READ)) ++ { ++ pthread_mutex_unlock(&parser->mutex); ++ GST_ERROR("Failed to map buffer."); ++ gst_buffer_unref(buffer); ++ return GST_FLOW_ERROR; ++ } ++ ++ stream->buffer = buffer; ++ } ++ else ++ { ++ if (stream->queue_capacity < stream->num_queued + 1) ++ { ++ size_t capacity = stream->queue_capacity != 0 ? stream->queue_capacity * 2 : 32; ++ GstBuffer **queue = malloc(capacity * sizeof(*stream->queued_buffers)); ++ if (!queue) ++ { ++ pthread_mutex_unlock(&parser->mutex); ++ GST_ERROR("Failed to allocate queue."); ++ gst_buffer_unref(buffer); ++ return GST_FLOW_ERROR; ++ } ++ memcpy(queue, stream->queued_buffers, stream->num_queued * sizeof(buffer)); ++ free(stream->queued_buffers); ++ stream->queue_capacity = capacity; ++ stream->queued_buffers = queue; ++ } ++ ++ stream->queued_buffers[stream->num_queued++] = buffer; + } + +- stream->buffer = buffer; ++ end_pts = GST_BUFFER_PTS(buffer); ++ if (GST_BUFFER_DURATION_IS_VALID(buffer)) ++ end_pts += GST_BUFFER_DURATION(buffer); ++ if (stream->latest_buffer_end_pts < end_pts) ++ stream->latest_buffer_end_pts = end_pts; + + pthread_mutex_unlock(&parser->mutex); + pthread_cond_broadcast(&parser->stream_event_cond); +@@ -1130,6 +1220,10 @@ static void free_stream(struct wg_parser_stream *stream) + stream->buffer = NULL; + } + ++ for (i = 0; i < stream->num_queued; i++) ++ gst_buffer_unref(stream->queued_buffers[i]); ++ free(stream->queued_buffers); ++ + for (i = 0; i < ARRAY_SIZE(stream->tags); ++i) + { + if (stream->tags[i]) +-- +2.45.1 + diff --git a/patches/wine-gst/0031-winegstreamer-Fix-race-between-wg_parser_stream_disa.patch b/patches/wine-gst/0031-winegstreamer-Fix-race-between-wg_parser_stream_disa.patch new file mode 100644 index 000000000..5bb25a46b --- /dev/null +++ b/patches/wine-gst/0031-winegstreamer-Fix-race-between-wg_parser_stream_disa.patch @@ -0,0 +1,27 @@ +From 78f5f554b501705fb40f2a587789695459d3fd67 Mon Sep 17 00:00:00 2001 +From: Torge Matthies +Date: Mon, 3 Jun 2024 11:05:38 +0200 +Subject: [PATCH 31/41] winegstreamer: Fix race between + wg_parser_stream_disable and GST_EVENT_FLUSH_STOP. + +--- + dlls/winegstreamer/wg_parser.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c +index fd749572b51..a58115c934f 100644 +--- a/dlls/winegstreamer/wg_parser.c ++++ b/dlls/winegstreamer/wg_parser.c +@@ -871,8 +871,7 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) + pthread_mutex_lock(&parser->mutex); + + stream->eos = false; +- if (stream->enabled) +- stream->flushing = false; ++ stream->flushing = false; + + pthread_mutex_unlock(&parser->mutex); + break; +-- +2.45.1 + diff --git a/patches/wine-gst/0023-HACK-winegstreamer-Add-a-resampler-to-wg_parser-for-.patch b/patches/wine-gst/0032-HACK-winegstreamer-Add-a-resampler-to-wg_parser-for-.patch similarity index 80% rename from patches/wine-gst/0023-HACK-winegstreamer-Add-a-resampler-to-wg_parser-for-.patch rename to patches/wine-gst/0032-HACK-winegstreamer-Add-a-resampler-to-wg_parser-for-.patch index 3d10b5bca..0f5840969 100644 --- a/patches/wine-gst/0023-HACK-winegstreamer-Add-a-resampler-to-wg_parser-for-.patch +++ b/patches/wine-gst/0032-HACK-winegstreamer-Add-a-resampler-to-wg_parser-for-.patch @@ -1,7 +1,7 @@ -From 3b97f6409bd01030c35d4d47cf412add892d82fb Mon Sep 17 00:00:00 2001 +From 94d7e0afd9deec15c6c2ca5b6b6360164db7f4ec Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 31 Jan 2024 17:42:54 +0100 -Subject: [PATCH 23/32] [HACK] winegstreamer: Add a resampler to wg_parser for +Subject: [PATCH 32/41] [HACK] winegstreamer: Add a resampler to wg_parser for raw audio. --- @@ -9,10 +9,10 @@ Subject: [PATCH 23/32] [HACK] winegstreamer: Add a resampler to wg_parser for 1 file changed, 4 insertions(+) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 4e1702893d0..83ba0237b3b 100644 +index a58115c934f..674edb83d47 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c -@@ -1266,6 +1266,10 @@ static bool stream_create_post_processing_elements(GstPad *pad, struct wg_parser +@@ -1359,6 +1359,10 @@ static bool stream_create_post_processing_elements(GstPad *pad, struct wg_parser if (!(element = create_element("audioconvert", "base")) || !append_element(parser->container, element, &first, &last)) return false; diff --git a/patches/wine-gst/0024-HACK-winegstreamer-Add-a-videoscale-element-to-wg_pa.patch b/patches/wine-gst/0033-HACK-winegstreamer-Add-a-videoscale-element-to-wg_pa.patch similarity index 83% rename from patches/wine-gst/0024-HACK-winegstreamer-Add-a-videoscale-element-to-wg_pa.patch rename to patches/wine-gst/0033-HACK-winegstreamer-Add-a-videoscale-element-to-wg_pa.patch index ff524b1b4..414a50da6 100644 --- a/patches/wine-gst/0024-HACK-winegstreamer-Add-a-videoscale-element-to-wg_pa.patch +++ b/patches/wine-gst/0033-HACK-winegstreamer-Add-a-videoscale-element-to-wg_pa.patch @@ -1,7 +1,7 @@ -From db64e51a09e838d83d4e3e84054cc4edca1c4d68 Mon Sep 17 00:00:00 2001 +From 7436110e9e7ceb0950658d3fa2fdd0088373ff85 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 31 Jan 2024 17:42:54 +0100 -Subject: [PATCH 24/32] [HACK] winegstreamer: Add a videoscale element to +Subject: [PATCH 33/41] [HACK] winegstreamer: Add a videoscale element to wg_parser for raw video. --- @@ -9,10 +9,10 @@ Subject: [PATCH 24/32] [HACK] winegstreamer: Add a videoscale element to 1 file changed, 8 insertions(+) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 83ba0237b3b..30a24905aa7 100644 +index 674edb83d47..f98bd4983f5 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c -@@ -1171,6 +1171,9 @@ static bool stream_create_post_processing_elements(GstPad *pad, struct wg_parser +@@ -1264,6 +1264,9 @@ static bool stream_create_post_processing_elements(GstPad *pad, struct wg_parser if (!(element = create_element("glcolorconvert", "base")) || !append_element(parser->container, element, &first, &last)) return false; @@ -22,7 +22,7 @@ index 83ba0237b3b..30a24905aa7 100644 if (!(element = create_element("gldownload", "base")) || !append_element(parser->container, element, &first, &last)) return false; -@@ -1254,6 +1257,11 @@ static bool stream_create_post_processing_elements(GstPad *pad, struct wg_parser +@@ -1347,6 +1350,11 @@ static bool stream_create_post_processing_elements(GstPad *pad, struct wg_parser /* Let GStreamer choose a default number of threads. */ gst_util_set_object_arg(G_OBJECT(element), "n-threads", "0"); diff --git a/patches/wine-gst/0025-HACK-mfmediaengine-Do-not-send-MF_MEDIA_ENGINE_EVENT.patch b/patches/wine-gst/0034-HACK-mfmediaengine-Do-not-send-MF_MEDIA_ENGINE_EVENT.patch similarity index 89% rename from patches/wine-gst/0025-HACK-mfmediaengine-Do-not-send-MF_MEDIA_ENGINE_EVENT.patch rename to patches/wine-gst/0034-HACK-mfmediaengine-Do-not-send-MF_MEDIA_ENGINE_EVENT.patch index 40e8d12e2..f2de9c281 100644 --- a/patches/wine-gst/0025-HACK-mfmediaengine-Do-not-send-MF_MEDIA_ENGINE_EVENT.patch +++ b/patches/wine-gst/0034-HACK-mfmediaengine-Do-not-send-MF_MEDIA_ENGINE_EVENT.patch @@ -1,7 +1,7 @@ -From 1d3a1206ada17b5a50a4f4d770ac8d4d4006bbee Mon Sep 17 00:00:00 2001 +From afdf6317f736daad68583cc0fde1fcecda28cfb6 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Sat, 2 Mar 2024 21:19:25 +0100 -Subject: [PATCH 25/32] [HACK] mfmediaengine: Do not send +Subject: [PATCH 34/41] [HACK] mfmediaengine: Do not send MF_MEDIA_ENGINE_EVENT_ERROR. Breaks AVPro Video (used by VRChat) when a IMFMediaEngine::GetError call inside the event handler doesn't return an @@ -14,10 +14,10 @@ This should be fixed properly. In the meantime, this hack works around the probl 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c -index 54ff4c62c5d..7064565c7dc 100644 +index 28a273616c8..65bb1608f27 100644 --- a/dlls/mfmediaengine/main.c +++ b/dlls/mfmediaengine/main.c -@@ -1405,11 +1405,21 @@ static HRESULT WINAPI media_engine_load_handler_Invoke(IMFAsyncCallback *iface, +@@ -1468,11 +1468,21 @@ static HRESULT WINAPI media_engine_load_handler_Invoke(IMFAsyncCallback *iface, } else { diff --git a/patches/wine-gst/0026-Marker-commit-do-not-put-into-MR.patch b/patches/wine-gst/0035-Marker-commit-do-not-put-into-MR.patch similarity index 72% rename from patches/wine-gst/0026-Marker-commit-do-not-put-into-MR.patch rename to patches/wine-gst/0035-Marker-commit-do-not-put-into-MR.patch index 1e3cac260..951f497cc 100644 --- a/patches/wine-gst/0026-Marker-commit-do-not-put-into-MR.patch +++ b/patches/wine-gst/0035-Marker-commit-do-not-put-into-MR.patch @@ -1,7 +1,7 @@ -From 7587df21b75991ff97e7c16c403410cd5a809120 Mon Sep 17 00:00:00 2001 +From 9713abd75bfb9c23759ebbeaf325e2ba26bfdf9f Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Mon, 25 Mar 2024 09:58:04 +0100 -Subject: [PATCH 26/32] === Marker commit, do not put into MR === +Subject: [PATCH 35/41] === Marker commit, do not put into MR === --- MAINTAINERS | 1 + diff --git a/patches/wine-gst/0027-DEBUG-winegstreamer-GST_LOG-GST_DEBUG.patch b/patches/wine-gst/0036-DEBUG-winegstreamer-GST_LOG-GST_DEBUG.patch similarity index 80% rename from patches/wine-gst/0027-DEBUG-winegstreamer-GST_LOG-GST_DEBUG.patch rename to patches/wine-gst/0036-DEBUG-winegstreamer-GST_LOG-GST_DEBUG.patch index 0ba1c744b..1bf854f26 100644 --- a/patches/wine-gst/0027-DEBUG-winegstreamer-GST_LOG-GST_DEBUG.patch +++ b/patches/wine-gst/0036-DEBUG-winegstreamer-GST_LOG-GST_DEBUG.patch @@ -1,17 +1,17 @@ -From 1a536d999475fd19dd8020fe5d45ad8fe9bddfa6 Mon Sep 17 00:00:00 2001 +From 765f3d4d4bbbf54b84602b9b2791e6b9520006d8 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Tue, 19 Mar 2024 10:20:49 +0100 -Subject: [PATCH 27/32] [DEBUG] winegstreamer: GST_LOG -> GST_DEBUG. +Subject: [PATCH 36/41] [DEBUG] winegstreamer: GST_LOG -> GST_DEBUG. --- dlls/winegstreamer/wg_parser.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c -index 30a24905aa7..5ddc9b677f9 100644 +index f98bd4983f5..3b6dc068ea2 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c -@@ -598,7 +598,7 @@ static NTSTATUS wg_parser_stream_notify_qos(void *args) +@@ -620,7 +620,7 @@ static NTSTATUS wg_parser_stream_notify_qos(void *args) /* This can happen legitimately if the sample falls outside of the * segment bounds. GStreamer elements shouldn't present the sample in * that case, but DirectShow doesn't care. */ @@ -20,7 +20,7 @@ index 30a24905aa7..5ddc9b677f9 100644 return S_OK; } if (!(event = gst_event_new_qos(params->underflow ? GST_QOS_TYPE_UNDERFLOW : GST_QOS_TYPE_OVERFLOW, -@@ -781,7 +781,7 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) +@@ -803,7 +803,7 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) struct wg_parser_stream *stream = gst_pad_get_element_private(pad); struct wg_parser *parser = stream->parser; @@ -29,16 +29,16 @@ index 30a24905aa7..5ddc9b677f9 100644 switch (event->type) { -@@ -892,7 +892,7 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu - struct wg_parser_stream *stream = gst_pad_get_element_private(pad); +@@ -951,7 +951,7 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu struct wg_parser *parser = stream->parser; + GstClockTime end_pts; - GST_LOG("stream %p, buffer %p.", stream, buffer); + GST_DEBUG("stream %p, buffer %p.", stream, buffer); pthread_mutex_lock(&parser->mutex); -@@ -918,7 +918,7 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu +@@ -977,7 +977,7 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu if (!stream->enabled) { @@ -47,7 +47,7 @@ index 30a24905aa7..5ddc9b677f9 100644 pthread_mutex_unlock(&parser->mutex); gst_buffer_unref(buffer); return GST_FLOW_OK; -@@ -949,7 +949,7 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu +@@ -1038,7 +1038,7 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu * reference to the stream object, which will release it in * wg_parser_stream_release_buffer(). */ @@ -56,7 +56,7 @@ index 30a24905aa7..5ddc9b677f9 100644 return GST_FLOW_OK; } -@@ -995,7 +995,7 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) +@@ -1084,7 +1084,7 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) struct wg_parser_stream *stream = gst_pad_get_element_private(pad); struct wg_parser *parser = stream->parser; @@ -65,7 +65,7 @@ index 30a24905aa7..5ddc9b677f9 100644 switch (query->type) { -@@ -1031,7 +1031,7 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) +@@ -1120,7 +1120,7 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) gst_structure_remove_fields(gst_caps_get_structure(caps, i), "framerate", "pixel-aspect-ratio", NULL); @@ -74,7 +74,7 @@ index 30a24905aa7..5ddc9b677f9 100644 if (filter) { -@@ -1308,7 +1308,7 @@ static void stream_decodebin_pad_added_cb(GstElement *element, GstPad *pad, gpoi +@@ -1401,7 +1401,7 @@ static void stream_decodebin_pad_added_cb(GstElement *element, GstPad *pad, gpoi struct wg_parser_stream *stream = user; struct wg_parser *parser = stream->parser; @@ -83,7 +83,7 @@ index 30a24905aa7..5ddc9b677f9 100644 if (gst_pad_is_linked(pad)) return; -@@ -1322,7 +1322,7 @@ static bool stream_decodebin_create(struct wg_parser_stream *stream) +@@ -1415,7 +1415,7 @@ static bool stream_decodebin_create(struct wg_parser_stream *stream) { struct wg_parser *parser = stream->parser; @@ -92,7 +92,7 @@ index 30a24905aa7..5ddc9b677f9 100644 if (!(stream->decodebin = create_element("decodebin", "base"))) return false; -@@ -1337,7 +1337,7 @@ static bool stream_decodebin_create(struct wg_parser_stream *stream) +@@ -1430,7 +1430,7 @@ static bool stream_decodebin_create(struct wg_parser_stream *stream) pthread_mutex_unlock(&parser->mutex); gst_element_sync_state_with_parent(stream->decodebin); @@ -101,7 +101,7 @@ index 30a24905aa7..5ddc9b677f9 100644 return true; } -@@ -1348,7 +1348,7 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user) +@@ -1441,7 +1441,7 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user) struct wg_parser *parser = user; GstCaps *caps, *caps2; @@ -110,7 +110,7 @@ index 30a24905aa7..5ddc9b677f9 100644 if (gst_pad_is_linked(pad)) return; -@@ -1391,7 +1391,7 @@ static void pad_removed_cb(GstElement *element, GstPad *pad, gpointer user) +@@ -1484,7 +1484,7 @@ static void pad_removed_cb(GstElement *element, GstPad *pad, gpointer user) unsigned int i; char *name; @@ -119,7 +119,7 @@ index 30a24905aa7..5ddc9b677f9 100644 for (i = 0; i < parser->stream_count; ++i) { -@@ -1450,7 +1450,7 @@ static GstFlowReturn issue_read_request(struct wg_parser *parser, guint64 offset +@@ -1543,7 +1543,7 @@ static GstFlowReturn issue_read_request(struct wg_parser *parser, guint64 offset pthread_mutex_unlock(&parser->mutex); @@ -128,7 +128,7 @@ index 30a24905aa7..5ddc9b677f9 100644 return ret; } -@@ -1559,7 +1559,7 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent, +@@ -1652,7 +1652,7 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent, { struct wg_parser *parser = gst_pad_get_element_private(pad); @@ -137,7 +137,7 @@ index 30a24905aa7..5ddc9b677f9 100644 if (offset == GST_BUFFER_OFFSET_NONE) offset = parser->next_pull_offset; -@@ -1573,7 +1573,7 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent, +@@ -1666,7 +1666,7 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent, if (!*buffer) *buffer = gst_buffer_new_and_alloc(0); gst_buffer_set_size(*buffer, 0); @@ -146,7 +146,7 @@ index 30a24905aa7..5ddc9b677f9 100644 return GST_FLOW_OK; } -@@ -1594,7 +1594,7 @@ static gboolean src_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) +@@ -1687,7 +1687,7 @@ static gboolean src_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) struct wg_parser *parser = gst_pad_get_element_private(pad); GstFormat format; @@ -155,7 +155,7 @@ index 30a24905aa7..5ddc9b677f9 100644 switch (GST_QUERY_TYPE(query)) { -@@ -1889,7 +1889,7 @@ static gboolean src_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) +@@ -1991,7 +1991,7 @@ static gboolean src_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) struct wg_parser *parser = gst_pad_get_element_private(pad); gboolean ret = TRUE; diff --git a/patches/wine-gst/0028-HACK-kernelbase-yt-dlp.exe-redirection-and-cmdline-m.patch b/patches/wine-gst/0037-HACK-kernelbase-yt-dlp.exe-redirection-and-cmdline-m.patch similarity index 95% rename from patches/wine-gst/0028-HACK-kernelbase-yt-dlp.exe-redirection-and-cmdline-m.patch rename to patches/wine-gst/0037-HACK-kernelbase-yt-dlp.exe-redirection-and-cmdline-m.patch index 1fd08a1b9..c740d4b9c 100644 --- a/patches/wine-gst/0028-HACK-kernelbase-yt-dlp.exe-redirection-and-cmdline-m.patch +++ b/patches/wine-gst/0037-HACK-kernelbase-yt-dlp.exe-redirection-and-cmdline-m.patch @@ -1,7 +1,7 @@ -From fdc8d8f2b7a9744d320753a800682d440e1e09c3 Mon Sep 17 00:00:00 2001 +From c4ba46169c51695a8bdf7447232a92f984683b12 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Thu, 28 Mar 2024 16:43:07 +0100 -Subject: [PATCH 28/32] [HACK] kernelbase: yt-dlp.exe redirection and cmdline +Subject: [PATCH 37/41] [HACK] kernelbase: yt-dlp.exe redirection and cmdline modification to read cookies from browser. --- diff --git a/patches/wine-gst/0029-mf-Schedule-stored-timers-for-the-original-time-inst.patch b/patches/wine-gst/0038-mf-Schedule-stored-timers-for-the-original-time-inst.patch similarity index 95% rename from patches/wine-gst/0029-mf-Schedule-stored-timers-for-the-original-time-inst.patch rename to patches/wine-gst/0038-mf-Schedule-stored-timers-for-the-original-time-inst.patch index b648fcbeb..3a74bccc0 100644 --- a/patches/wine-gst/0029-mf-Schedule-stored-timers-for-the-original-time-inst.patch +++ b/patches/wine-gst/0038-mf-Schedule-stored-timers-for-the-original-time-inst.patch @@ -1,7 +1,7 @@ -From d60a28aa145260f16e8d73632380689fb9fcc014 Mon Sep 17 00:00:00 2001 +From 2e03cb907dd41679b2e4b3de15f67353007598b6 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Fri, 23 Feb 2024 21:45:44 +0100 -Subject: [PATCH 29/32] mf: Schedule stored timers for the original time +Subject: [PATCH 38/41] mf: Schedule stored timers for the original time instead of calling callbacks immediately when changing presentation clock state. diff --git a/patches/wine-gst/0030-mf-Start-forwarding-samples-only-at-the-PTS-of-the-f.patch b/patches/wine-gst/0039-mf-Start-forwarding-samples-only-at-the-PTS-of-the-f.patch similarity index 98% rename from patches/wine-gst/0030-mf-Start-forwarding-samples-only-at-the-PTS-of-the-f.patch rename to patches/wine-gst/0039-mf-Start-forwarding-samples-only-at-the-PTS-of-the-f.patch index 842058a13..e114f5c07 100644 --- a/patches/wine-gst/0030-mf-Start-forwarding-samples-only-at-the-PTS-of-the-f.patch +++ b/patches/wine-gst/0039-mf-Start-forwarding-samples-only-at-the-PTS-of-the-f.patch @@ -1,7 +1,7 @@ -From f948bcc6eefc6d94c66b06243073aa31dfdf83c9 Mon Sep 17 00:00:00 2001 +From 069f52e82cb1a6ff21354bb7a130d53c0e66d9a9 Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Fri, 23 Feb 2024 21:50:22 +0100 -Subject: [PATCH 30/32] mf: Start forwarding samples only at the PTS of the +Subject: [PATCH 39/41] mf: Start forwarding samples only at the PTS of the first sample. Hides desynchronization in applications that ignore the PTS, e.g. VRChat. diff --git a/patches/wine-gst/0031-ntdll-Use-unixcall-instead-of-syscall-for-QueryPerfo.patch b/patches/wine-gst/0040-ntdll-Use-unixcall-instead-of-syscall-for-QueryPerfo.patch similarity index 96% rename from patches/wine-gst/0031-ntdll-Use-unixcall-instead-of-syscall-for-QueryPerfo.patch rename to patches/wine-gst/0040-ntdll-Use-unixcall-instead-of-syscall-for-QueryPerfo.patch index 51ce6cd0b..9aeca9529 100644 --- a/patches/wine-gst/0031-ntdll-Use-unixcall-instead-of-syscall-for-QueryPerfo.patch +++ b/patches/wine-gst/0040-ntdll-Use-unixcall-instead-of-syscall-for-QueryPerfo.patch @@ -1,7 +1,7 @@ -From f1acb3ea81d1d99a58256be921ef2e9817eb518b Mon Sep 17 00:00:00 2001 +From 2d5bb39793ec61127f75aa1a263ce45db829e59e Mon Sep 17 00:00:00 2001 From: Torge Matthies Date: Wed, 24 Apr 2024 22:00:49 +0200 -Subject: [PATCH 31/32] ntdll: Use unixcall instead of syscall for +Subject: [PATCH 40/41] ntdll: Use unixcall instead of syscall for QueryPerformanceCounter. --- diff --git a/wine b/wine index cd0172ffb..7374ef563 160000 --- a/wine +++ b/wine @@ -1 +1 @@ -Subproject commit cd0172ffb83cb7e92d8884117725ae4ef1bedfd8 +Subproject commit 7374ef563eac28f94e0ce9b6b16929496bb3af4e