|
| 1 | +From 6a85fac4525a9865b560cb39a60b46a9bfdebac5 Mon Sep 17 00:00:00 2001 |
| 2 | +From: =?UTF-8?q?Enrique=20Oca=C3=B1a=20Gonz=C3=A1lez?= < [email protected]> |
| 3 | +Date: Mon, 29 May 2023 20:55:43 +0200 |
| 4 | +Subject: [PATCH] streamsynchronizer: Consider streams having received |
| 5 | + stream-start as waiting |
| 6 | + |
| 7 | +When using the custom WebKitMediaSrc element (used by WebKit and able to |
| 8 | +perform an initial seek in playbin), a stall caused by streamsynchronizer |
| 9 | +was detected during an initial seek. The flow of events revealed that the |
| 10 | +intertwining of the initial configuration of the streams with the reset |
| 11 | +caused by the flush events from the seek left streamsynchronizer in an |
| 12 | +inconsistent state: |
| 13 | + |
| 14 | + streamsynchronizer0:sink_0 (video) events, starting before the seek: |
| 15 | + stream-start --> Sets the stream to wait |
| 16 | + flush-stop --> Clears the stream wait flag |
| 17 | + caps |
| 18 | + tag |
| 19 | + segment |
| 20 | + stream-collection |
| 21 | + (buffers start to come and flow properly) |
| 22 | + |
| 23 | + streamsynchronizer0:sink_1 (audio) events, happening after seek: |
| 24 | + (no flush events, because the stream hadn't been initialized when the seek happened) |
| 25 | + stream-start --> Sets the stream to wait |
| 26 | + caps |
| 27 | + segment |
| 28 | + (stalled because the stream is in wait mode!) |
| 29 | + |
| 30 | +The code in streamsynchronizer expects that all the streams are in wait |
| 31 | +state before releasing all of them at once. The flush on the video stream |
| 32 | +broke that assumption and that's why the audio stream is never released in |
| 33 | +that scenario. |
| 34 | + |
| 35 | +Avoiding the clearing of the wait flag on flush-stop isn't an actual solution |
| 36 | +to the problem, as it creates other side effects and at least makes the |
| 37 | +gst-editing-services/seek_with_stop test to timeout. The alternate solution |
| 38 | +implemented in this patch consists on recording when the stream-start event is |
| 39 | +received and then consider those started streams equally valid as those in |
| 40 | +waiting state when evaluating if all the streams should be unblocked. |
| 41 | + |
| 42 | +See: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4544 |
| 43 | +--- |
| 44 | + gst/playback/gststreamsynchronizer.c | 7 +++++-- |
| 45 | + 1 file changed, 5 insertions(+), 2 deletions(-) |
| 46 | + |
| 47 | +diff --git a/gst/playback/gststreamsynchronizer.c b/gst/playback/gststreamsynchronizer.c |
| 48 | +index 41836f79b..fd4f523a4 100644 |
| 49 | +--- a/gst/playback/gststreamsynchronizer.c |
| 50 | ++++ b/gst/playback/gststreamsynchronizer.c |
| 51 | +@@ -70,6 +70,7 @@ typedef struct |
| 52 | + gboolean flushing; /* set after flush-start and before flush-stop */ |
| 53 | + gboolean seen_data; |
| 54 | + gboolean send_gap_event; |
| 55 | ++ gboolean seen_stream_start; |
| 56 | + GstClockTime gap_duration; |
| 57 | + |
| 58 | + GstStreamFlags flags; |
| 59 | +@@ -448,13 +449,14 @@ gst_stream_synchronizer_sink_event (GstPad * pad, GstObject * parent, |
| 60 | + GST_DEBUG_OBJECT (pad, "Stream %d changed", stream->stream_number); |
| 61 | + |
| 62 | + stream->wait = TRUE; |
| 63 | ++ stream->seen_stream_start = TRUE; |
| 64 | + |
| 65 | + for (l = self->streams; l; l = l->next) { |
| 66 | + GstSyncStream *ostream = l->data; |
| 67 | + |
| 68 | + all_wait = all_wait && ((ostream->flags & GST_STREAM_FLAG_SPARSE) |
| 69 | +- || (ostream->wait && (!have_group_id |
| 70 | +- || ostream->group_id == group_id))); |
| 71 | ++ || ((ostream->wait || ostream->seen_stream_start) |
| 72 | ++ && (!have_group_id || ostream->group_id == group_id))); |
| 73 | + if (!all_wait) |
| 74 | + break; |
| 75 | + } |
| 76 | +@@ -1130,6 +1132,7 @@ gst_stream_synchronizer_change_state (GstElement * element, |
| 77 | + gst_segment_init (&stream->segment, GST_FORMAT_UNDEFINED); |
| 78 | + stream->gap_duration = GST_CLOCK_TIME_NONE; |
| 79 | + stream->wait = FALSE; |
| 80 | ++ stream->seen_stream_start = FALSE; |
| 81 | + stream->is_eos = FALSE; |
| 82 | + stream->eos_sent = FALSE; |
| 83 | + stream->flushing = FALSE; |
| 84 | +-- |
| 85 | +2.34.1 |
| 86 | + |
0 commit comments