Majorly change the way that splitmuxsink collects
incoming data and sends it to the output, so that it
makes all decisions about when / where to split files
on the input side.
Use separate queues for each stream, so they can be
grown individually and kept as small as possible.
This removes raciness I observed where sometimes
some data would end up put in a different output file
over multiple runs with the same input.
Also fixes hangs with input queues getting full
and causing muxing to stall out.
Add a new signal for formatting the filename, which receives
a GstSample containing the first buffer from the reference
stream that will be muxed into that file.
Useful for creating filenames that are based on the
running time or other attributes of the buffer.
To make it work, opening of files and setting filenames is
now deferred until there is some data to write to it,
which also requires some changes to how async state changes
and gap events are handled.
Make sure the state of the parser is set to
collecting streams before chaining up to the
parent change_state() method, to close a
small window that can cause playback to
never commence.
Use GQueue instead of a GSList so we don't have to traverse
the whole list to append something every time. And it also
keeps track of the number of items in it for us.
Add a function to add filenames to the list of old files and
use it in more places, so that memory doesn't build up in
other modes either if no max_files limit is specified.
https://bugzilla.gnome.org/show_bug.cgi?id=766991
Technically we weren't leaking the memory, just storing it internally
and never using it until the element is freed. But we'd still use more
and more memory over time, so this is not good over longer periods
of time. Only keep track of files if there's actually a limit set,
so that we will prune the list from time to time.
https://bugzilla.gnome.org/show_bug.cgi?id=766991
splitmuxsink requests pad from element using pad template like "video_%u", "audio_%u" and "sink_%d". This is true for most of the muxers.
But splitmuxsink not able to request pad to flvmux as flvmux has "audio" and "video" as pad templates.
fix: splitmuxsink should fallback to "audio" and "video" when template not found.
https://bugzilla.gnome.org/show_bug.cgi?id=774507
Do not use last buffer TS + buffer duration because buffer duration
might be inaccurate, especially for frame rates like 30fps where a
rounding error is observed.
https://bugzilla.gnome.org/show_bug.cgi?id=773785
Commit 83e718 added a pad template to splitmux request
pads, which means that GstElement now releases the pads on
dispose, but after having removed all elements in the bin
and unlinked them. Make sure we can handle cleanup in that case
without throwing assertions.
https://bugzilla.gnome.org/show_bug.cgi?id=773784
The pacing of the overall muxing is controlled
by the video GOPs arriving, so we can only handle
1 video stream, and the request pad is named accordingly.
Ignore a request for a 2nd video pad if there's already
an active one.
Found via the Jenkins CI:
FAILED: subprojects/gst-plugins-good/gst/multifile/gstmultifile@sha/gstsplitmuxsink.c.o
[...]
In file included from ../subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsink.h:24:0,
from ../subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsink.c:59:
../subprojects/gst-plugins-base/gst-libs/gst/pbutils/pbutils.h:30:43: fatal error: gst/pbutils/pbutils-enumtypes.h: No such file or directory
#include <gst/pbutils/pbutils-enumtypes.h>
^
compilation terminated.
https://ci.gstreamer.net/job/GStreamer-master-meson/263/console
If the seek stop point (or start, during reverse play)
was within the segment we just finished, go EOS immediately
instead of proceeding through all other parts and sending
0 length seeks to them.
https://bugzilla.gnome.org/show_bug.cgi?id=772138
When one part moves ahead of the others - due to excessive
downstream queueing, or really small input files - then
we can end up activating parts more than once. That can lead to
effects like shutting down pad tasks prematurely.
https://bugzilla.gnome.org/show_bug.cgi?id=772138
This reverts commit f1ceaab02f.
This broke atomic file writes in "buffer" mode. It did make
sure that any streamheaders are prepended to each file in
buffer mode as well, but that's not really needed in practice,
whereas atomic file writes are, so let's restore the status
quo ante for now since this was primarily a code cleanup anyway,
and if anyone needs to streamheaders in buffer mode too they
can make a patch to implement that differently. Re-implementing
the atomic writes in the element also seems way too much work.
https://bugzilla.gnome.org/show_bug.cgi?id=766990
On 32-bit x86: gstsplitmuxsink.c:966:31: warning: format ‘%u’ expects
argument of type ‘unsigned int’, but argument 9 has type
‘guint64 {aka long long unsigned int}’
https://github.com/mesonbuild/meson
With contributions from:
Tim-Philipp Müller <tim@centricular.com>
Jussi Pakkanen <jpakkane@gmail.com> (original port)
Highlights of the features provided are:
* Faster builds on Linux (~40-50% faster)
* The ability to build with MSVC on Windows
* Generate Visual Studio project files
* Generate XCode project files
* Much faster builds on Windows (on-par with Linux)
* Seriously fast configure and building on embedded
... and many more. For more details see:
http://blog.nirbheek.in/2016/05/gstreamer-and-meson-new-hope.htmlhttp://blog.nirbheek.in/2016/07/building-and-developing-gstreamer-using.html
Building with Meson should work on both Linux and Windows, but may
need a few more tweaks on other operating systems.
This reverts commit fa008f271a.
async-handling in GstBin causes the pipeline to spin at 100%
CPU as the top-level pipeline tries to change that state
to PLAYING constantly. This is a workaround for a core
problem, essentially, but an improvement in this case for now.
After dropping the splitmux lock, re-check the state,
don't just fall through and sleep unconditionally,
as we may have already missed the wakeup.
https://bugzilla.gnome.org/show_bug.cgi?id=769514
Use signed clock times for running time everywhere
so that we handle negative running times without
going haywire, similar to what queue and multiqueue
do these days.
Set the async-handling property on GstBin to let it manage
async-handling instead of the local handling from the previous
commit. Works because of #174a5e in core
When switching fragments, hide the async-start/async-done
messages from the parent bin, as otherwise we sometimes (very rarely)
hang in PAUSED instead of returning / continuing to PLAYING
state.
This signal allows a user to directly return a sorted list of
files to be joined, so that they don't have to follow the
filename pattern that the "location" property expects.
https://bugzilla.gnome.org/show_bug.cgi?id=753625
Make sure that all data is drained out when the reference pad
goes EOS. Fixes a problem where data that arrives on other
pads after the reference pad finishes can stall forever and
never pass EOS.
https://bugzilla.gnome.org/show_bug.cgi?id=763711
Deadlock occurs when splitting files if one stream received no buffer during
the first GOP of the next file. That can happen in that scenario for example:
1) The first GOP of video is collected, it has a duration of 10s.
max_in_running_time is set to 10s.
2) Other streams catchup and we receive the first subtitle buffer at ts=0 and
has a duration of 1min.
3) We receive the 2nd subtitle buffer with a ts=1min. in_running_time is set to
1min. That buffer is blocked in handle_mq_input() because
max_in_running_time is still 10s.
4) Since all in_running_time are now > 10s, max_out_running_time is now set to
10s. That first GOP gets recorded into the file. The muxer pop buffers out
of the mq, when it tries to pop a 2nd subtitle buffer it blocks because the
GstDataQueue is empty.
5) A 2nd GOP of video is collected and has a duration of 10s as well.
max_in_running_time is now 20s. Since subtitle's in_running_time is already
1min, that GOP is already complete.
6) But let's say we overran the max file size, we thus set state to
SPLITMUX_STATE_ENDING_FILE now. As soon as a buffer with ts > 10s (end of
previous GOP) arrives in handle_mq_output(), EOS event is sent downstream
instead. But since the subtitle queue is empty, that's never going to
happen. Pipeline is now deadlocked.
To fix this situation we have to:
- Send a dummy event through the queue to wakeup output thread.
- Update out_running_time to at least max_out_running_time so it sends EOS.
- Respect time order, so we set out_running_tim=max_in_running_time because
that's bigger than previous buffer and smaller than next.
https://bugzilla.gnome.org/show_bug.cgi?id=763711
If we have an error during fwrite call, file stays open and thus next
incoming buffer will trigger an assert when trying to opening a new
file.
This happens if we do not restart element, file is closed at stop, and
if application handles the returned GST_FLOW_ERROR to keep bin alive.
https://bugzilla.gnome.org/show_bug.cgi?id=762434
Don't increment running time from every buffer. The correct
logic to only increment when running time advances is a
little further down, so delete this left-over line.
Instead, delay it until all request pads have been released. This is
because the release_pad() vfunc requires the multiqueue and muxer to
be there in order to release their request pads as well. If those
elements are destroyed earlier, release_pad() does not work, no
pads are released and some resources are leaked.
https://bugzilla.gnome.org/show_bug.cgi?id=753622
mux_start_time refers to the running_time of the buffer
that goes first in the output file. Normally this time is
0, so this variable is initialized to 0 during the state
change to PAUSED.
However, when dealing with dynamic pipelines and starting
a recording while the pipeline has already run for a while,
the running_time of the first buffer is > 0 and this causes
a problem with detecting the end of the first file(s) when
splitting by duration, because the code will later compare
the threshold_time with (last buffer running_time - mux_start_time)
and will get it wrong until mux_start_time advances enough
to make this difference < threshold_time, creating empty files
in the meantime.
https://bugzilla.gnome.org/show_bug.cgi?id=753624
When we haven't started yet, set the start_index when we set the index property,
so that we start at the right index position after the initial seek. The index
property was never really meant to be for writing, but it used to work, so let's
support it for backwards compatibility.
https://bugzilla.gnome.org/show_bug.cgi?id=739472
If the GOP is completed, pads have to start gathering for the
next one but it is possible that the the state might go to
COLLECTING_GOP_START and back to WAITING_GOP_COMPLETE before the
thread has a chance to wake up and proceed, leaving it trapped in
the check_completed_gop loop and deadlocking the other threads
waiting for it to advance.
To solve it, this patch also checks that tha input running time
hasn't changed to prevent this scenario.
Don't hold the main splitmux part lock over
the parent state change function, as it prevents
posting error messages that happen. Since the purpose
is to prevent typefinding from proceeding, use a
separate mutex just for that.
In certain applications, splitting into files named after a base
location template and an incremental sequence number is not enough.
This signal gives more fine-grained control to the application to
decide how to name the files.
https://bugzilla.gnome.org/show_bug.cgi?id=750106
Fix 2 startup races when things happen too quickly, and 1
at shutdown by holding a ref to the pads in use until the
loop functions exit.
Handle errors activating file parts and publish them on
the bus.
https://bugzilla.gnome.org/show_bug.cgi?id=750747
Sometimes, extra async-start/done from the internal sink
while the element is still starting up can cause splitmuxsink
to stall in PAUSED state when it has been set to PLAYING
by the app. Drop the child's async-start/done messages while
switching, so they don't cause state changes at the
splitmuxsink level.
https://bugzilla.gnome.org/show_bug.cgi?id=750747
When deciding whether it's time to switch to a new file, take into
account data that's been released for pushing, but hasn't yet
been pushed - because downstream is slow or the threads haven't been
scheduled.
Fixes a race in the unit test and probably in practice - sometimes
failing to switch when it should for an extra GOP or two.
Also fix a problem in splitmuxsrc where playback sometimes
stalls at startup if types are found too quickly.
https://bugzilla.gnome.org/show_bug.cgi?id=750747
This new mode ensures that files will never exceed a certain duration
based on incoming buffer PTS (and duration if present)
Note:
* You need timestamped buffers (duh). If some of the incoming buffers don't
have PTS, then it will just accept them in the current file
This property can be used in combination with next-file=max-size
(and perhaps a future next-file=max-duration) to make sure that
each file part starts cleanly with a key frame and the appropriate headers.
In order for this property to work correctly, upstream elements should make
sure than any headers that need to be written in a standalone file are:
1) in the streamheader caps field
2) and/or in the stream as one or more buffers marked with GST_BUFFER_FLAG_HEADER
that are just before the keyframe buffer
This is useful for MPEG-TS/MPEG-PS file segmenting in
combination with mpegtsmux or mpegpsmux.
Original patch by: Tim-Philipp Müller <tim@centricular.com>
because _release_pad tries to release it from ctx->sinkpad, which is
multiqueue's sink pad, and currently fails because the probe is not
installed there
When multifilesink is operating in any mode other than one file
per buffer, the last file created won't have a file message posted
as multifilesink doesn't handle the EOS event.
This patch fixes it by using the last position to post a file
message when EOS is received. This should ensure at least the
time related data and the filename are posted to the application
or other elements
https://bugzilla.gnome.org/show_bug.cgi?id=747000
Handle the case where a short file reaches EOS while we're still
waiting for no-more-pads, and make sure we continue to the internal
READY state for real playback to work properly later.
Implement 2 new elements - splitmuxsink and splitmuxsrc.
splitmuxsink is a bin which wraps a muxer and takes 1 video stream,
plus audio/subtitle streams, and starts a new file
whenever necessary to avoid overrunning a threshold of either bytes
or time. New files are started at a keyframe, and corresponding audio
and subtitle streams are split at packet boundaries to match
video GOP timestamps.
splitmuxsrc is a corresponding source element which handles
the splitmux:// URL and plays back all component files,
reconstructing the original elementary streams as it goes.
They are very confusing for people, and more often than not
also just not very accurate. Seeing 'last reviewed: 2005' in
your docs is not very confidence-inspiring. Let's just remove
those comments.
We assume for now that all buffers in a buffer list
should end up in the same file (so we can group GOPs
in buffer lists, for example). Could optimise this
a bit to avoid the memcpy.
Handle corner case where we try to read beyond the end of the
last file part, in which case we want to return a short read.
If we get fewer bytes than expected for any other file part,
we should just error out, since something fishy's going on
then.
Looks like some parsers (in some versions at least) expect the
offsets to be set, and behave weird if that's not the case
(e.g. off-by-one in h264parse).