Prevent a condition where splitmuxsink won't go back to NULL state
after a child element fails to change state by making sure that
a READY->READY state change doesn't fail, and by returning
GST_FLOW_ERROR or GST_FLOW_FLUSHING upstream to shut down streaming
as quickly as possible.
This can happen after (for example) setting an invalid filename
on the sink element. In that case, the READY->PAUSED transition
fails, but with internal elements still in the NULL state. Trying
to set splitmuxsink back to NULL then ends up trying to bring
those NULL elements up to READY with a READY->READY transition,
(which fails, prevent splitmuxsink from getting to NULL)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/1023>
https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/798
introduced a check in the need-new-fragment logic to avoid starting a
new fragment unless there has been some data on the reference stream,
but the check is done against the number of bytes that have been
received on the input, not the number that were released for output
into the current fragment.
Fix the check to remember and test against bytes that have been sent
for output.
This also fixes a problem where starting a new fragment fails to
request a new filename from the format-location signal.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/833>
Add a new state for ending the overall stream, and use it to decide
whether to pass the final EOS message up the bus instead of dropping
it. Fixes a small race that makes the testsuite sometimes not generate
the last fragment(s) sometimes because the wrong EOS gets
allowed through too early.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/798>
Using the element state lock to avoid splitmuxsink shutting
down while doing element manipulations can lead to a deadlock on
shutdown if a fragment switch happens at exactly the wrong moment.
Use a private mutex and a shutdown boolean instead.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/798>
If a pad gets into the check_completed_gop method and then
the underlying conditions change on the reference context,
things could get stuck in a busy loop when the context should
instead jump back out and wait for more data.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/798>
- Release the split mux lock while removing the probes
- Flush the sinkpad to unblock other pads
- Turn check_completed_gop into a do while statement, when
waking up we want to recheck whether the current GOP is
ready for sending
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/719>
* Trying to disconnect a stream from a running splitmuxsink by flushing
it results in the FLUSH_START blocking in the stream queue's
gst_pad_pause_task because the flush did not unblock
complete_or_wait_on_out, so add a check for ctx->flushing there.
* Add a GST_SPLITMUX_BROADCAST_INPUT so check_completed_gop notices
flushing changed and the incoming push is unblocked.
* Pass the FLUSH_STOP along to the muxer without waiting.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/687>
The calculated threshold for timecode might be varying depending on
"max-size-timecode" and framerate.
For instance, with framerate 29.97 (30000/1001) and
"max-size-timecode=00:02:00;02", every fragment will have identical
number of frames 3598. However, when "max-size-timecode=00:02:00;00",
calculated next keyframe via gst_video_time_code_add_interval()
can be different per fragment, but this is the nature of timecode.
To compensate such timecode drift, we should keep track of expected
timecode of next fragment based on observed timecode.
If the start of the GOP is >= the requested running time, put it into a
new fragment. That is, split-at-running-time would always ensure that a
split happens as early as possible after the given running time.
Previously it was comparing against the current incoming timestamp,
which does not tell us what we actually want to know as it has no direct
relation to the GOP start/end.
The queued time includes the duration of the last queued frame
(i.e., new keyframe) so the condition check should not be inclusive.
Note that the new fragment will be cut excluding the last frame
and therefore if the condition is inclusive way,
the fragment might have one frame shorter duration for all keyframe
stream such as jpeg or all-inter video streams.
Since the commit 94bb76b6b9, splitmuxsink
will split fragments based on queued time and the threshold of that.
So don't need to store the next timecode for split decision.
Not only the requested keyframe time, the queued size should be
a criterion for the split decision of timecode based mode
(same as max-size-time based split case).
If not configuring the sinks via the "location" property this can be
useful to know for which sink the fragment was actually opened/closed,
especially if finalization of the fragments is happening asynchronously.
Applications might handle locations and generally configuration of the
sink by themselves instead of having splitmuxsink set the location on
the sink. Nonetheless it makes sense to increment the fragment_id that
is passed to the signal so that applications know which fragment is
requested.
An application might try to access splitmuxsink from sync message handler
by g_object_{get,set} which takes lock also. In general, we don't
take lock around message handler.
Add a property which explicitly maps splitmuxsink pads to the
muxer pads they should connect to, overriding the implicit logic
that tries to match pads but yields arbitrary names.
When running in async-finalize mode, request new pads from the muxer
using the same names as old pads, instead of letting the muxer assign
new ones based on the pad template name.
The primary video stream is used to select fragment cut points
at keyframe boundaries. Auxilliary video streams may be
broken up at any packet - so fragments may not start with a keyframe
for those streams.
Make the debug output less confusing by not mentioning a src
pad when doing calculations on the sink pad side.
Improve debug around why a GOP is considered overflowing a fragment
There is only a single sink element in async-finalize mode, and we would
keep the running time from previous fragments set in that case. As we
don't ever set the running time for the very last fragment on EOS, this
would mean that the closing time reported for the very last fragment is
the same as the closing time of the previous fragment.
Apart from the obvious drawbacks of hardcoding, the drawback here was
that, if we subtracted 2 frames (instead of 2.6) from the target running
time, we'd request the next keyframe a bit too far into the future,
which would make our files split at the wrong position.
https://bugzilla.gnome.org/show_bug.cgi?id=797293
For drop-frame framerates, when the expected next max timecode wraps
around at the end of the day, we have to subtract the offset of the
daily jam, otherwise we end up with a duration that's a few frames too
long.
https://bugzilla.gnome.org/show_bug.cgi?id=797270