In reverse playback, buffers have to be displayed at buffer.stop running
time, otherwise a same set of buffer can't be displayed in the exact opposite
order to forward playback.
For example, seeking a video stream at 1fps with start=0, stop=5s, rate=1.0
will display the following buffers:
b0.pts = 0s, b0.duration = 1s - at running time = 0s
b1.pts = 1s, b1.duration = 1s - at running time = 1s
b2.pts = 2s, b2.duration = 1s - at running time = 2s
b3.pts = 3s, b3.duration = 1s - at running time = 3s
b4.pts = 4s, b4.duration = 1s - at running time = 4s
<wait at EOS for 1second>
Now, playing that reverse with start=0, stop=5s, rate=1.0 has to display
the following buffers:
b0.pts = 4s, b0.duration = 1s - at running time = 0s
b1.pts = 3s, b1.duration = 1s - at running time = 1s
b2.pts = 2s, b2.duration = 1s - at running time = 2s
b3.pts = 1s, b3.duration = 1s - at running time = 3s
b4.pts = 0s, b4.duration = 1s - at running time = 4s
<wait at EOS for 1second>
With the previous code, it reproduced the following:
b0.pts = 4s, b0.duration = 1s - at running time = 1s
b1.pts = 3s, b1.duration = 1s - at running time = 2s
b2.pts = 2s, b2.duration = 1s - at running time = 3s
b3.pts = 1s, b3.duration = 1s - at running time = 4s
b4.pts = 0s, b4.duration = 1s - at running time = 5s
<NO WAIT AT EOS AND POST EOS RIGHT AWAY>
This is being tested with the `validate.launch_pipeline.sink.reverse_playback_clock_waits.*`
set of tests
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/450>
In reverse playback, buffers are played back from buffer.stop
(buffer.pts + buffer.duration) to buffer.pts, which means that the
position after the buffer is consumed is buffer.pts, not buffer.pts -
buffer.duration.
Without that change, and when `automatic_eos` feature is on,
we were dropping the last buffers as marking the stream EOS one buffer
too soon.
This is now being tested extensively by GstValidate in the
`validate.test.clock_sync.*` set of tests.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/450>
To allow the refcounting tracer to work better. In childproxy/iterator
these might be plain GObjects but gst_object_unref() also works on them.
In other places where it is never GstObject, g_object_unref() is kept.
Even when pulling a new 64KB buffer from upstream, don't return
more data than was asked for in the pull_range() method and then
return less later, as that confused subclasses like h264parse.
Add a unit test that when a subclass asks for more data, it always
receives a larger buffer on the next iteration, never less.
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/530
When running in pull mode (for e.g. mp3 reading),
baseparse currently reads 64KB from upstream, then mp3parse
consumes typically around 417/418 bytes of it. Then
on the next loop, it will read a full fresh 64KB again,
which is a big waste.
Fix the read loop to use the available cache buffer first
before going for more data, until the cache drops to < 1KB.
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/518
What may happen is that during the course of processing a buffer,
all of the pads in a flow combiner may disappear. In this case, we
would return NOT_LINKED. Instead return whatever the input flow return
was.
This has the same function as the negotiate() functions in various other
base classes and is required to be able to completely re-implement
submit_input_buffer() in subclasses.
When we do not have any information about DTSs we shouldn't try to make
them up, moreover after seeking `segment->start` has nothing to do with
the next buffer timing (and is probably after the actual buffer timestamp)
and since, since fa8312472f
we do:
```
if (buffer->dts > buffer->dts)
buffer->pts = buffer->dts
```
we end up setting `buffer->pts = segment->start` which is plain
broken and leads to downstream decoder accept the first buffer
as it will be inside the segment (its pts==segment->start) which
basically means accurate seeking behaves mostly the same way as
keyframe seeks.
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/492
As soon as gstcheck potentially calls out to code it does not
control, such as gst_element_request_pad, all assertions about
pad refcounts go out the window.
We were checking to make sure the buffer's DTS wouldn't be after its
PTS. However, the check would also trigger when DTS is NONE, which is
e.g. in the case of some broken cameras.
Fixes#470
If, for example, we are accumulating rounding errors from the buffer
duration when calculating the PTS/DTS, it can happen that the buffer
thinks it should be presented before it's decoded. In that case we just
clamp the DTS.
Post instant-rate-request message when receiving an instant-rate-change
event, and handle the incoming instant-rate-sync-time events from the
pipeline.
If the expected size is bigger than the actual buffer size, it would
memcmp random memory which could lead to crashes instead of proper error
reporting.
The virtual method named `get_caps` in both `GstBaseSrc` and
`GstBaseSink` has a `filter` parameter which can be `NULL` (the
default implementation in GstBaseSrc already considers the case).
Before this commit, there was no gtk-doc annotation representing this
fact, which caused the corresponding entry in the GIR file to also
miss this fact.
This caused bugs in other places, such inducing the Vala compiler to
introduce a wrongly assert on `(filter != NULL)` in every
implementation of the `get_caps` method implemented in Vala.
By passing NULL to `g_signal_new` instead of a marshaller, GLib will
actually internally optimize the signal (if the marshaller is available
in GLib itself) by also setting the valist marshaller. This makes the
signal emission a bit more performant than the regular marshalling,
which still needs to box into `GValue` and call libffi in case of a
generic marshaller.
Note that for custom marshallers, one would use
`g_signal_set_va_marshaller()` with the valist marshaller instead.
../libs/gst/check/libcheck/check.c:617:15: error: result of comparison of constant 4294967295 with expression of type 'clockid_t' is always false [-Werror,-Wtautological-constant-out-of-range-compare]
if (clockid == -1) {
~~~~~~~ ^ ~~
Silence -Wformat-nonliteral warnings from the internal copy of libcheck
../subprojects/gstreamer/libs/gst/check/libcheck/check.c:379:29: warning: format string is not a string literal [-Wformat-nonliteral]
vsnprintf (buf, BUFSIZ, msg, ap);
^~~
../subprojects/gstreamer/libs/gst/check/libcheck/check_error.c:48:21: warning: format string is not a string literal [-Wformat-nonliteral]
vfprintf (stderr, fmt, args);
^~~
../subprojects/gstreamer/libs/gst/check/libcheck/check_str.c:92:29: warning: format string is not a string literal [-Wformat-nonliteral]
n = vsnprintf (p, size, fmt, ap);
^~~
Otherwise it can happen that we start waiting for another pad, while one
pad already has events that can be handled and potentially also a buffer
that can be handled. That buffer would then however not be accessible by
the subclass from GstAggregator::get_next_time() as there would be the
events in front of it, which doesn't allow the subclass then to
calculate the next time based on already available buffers.
As a side-effect this also allows removing the duplicated event handling
code in the aggregate function as we'll always report pads as not ready
when there is a serialized event or query at the top of at least one
pad's queue.
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/428
The install kwarg on configure_file() was only added in
Meson 0.50 but we're targetting older versions as well,
which caused a warning. The install kwarg is not needed
here as we specify install_dir, so we can just drop it.
Fixes#379
The documentation says that this allows the subclass to signal that it
needs more data before it can decide on caps, so let's actually
implement it that way.
This is similar to what demuxers do, and necessary when multiple
sinks get seeked downstream of the aggregator: if we forward
duplicated seeks upstream, elements such as demuxers may drop
the flushing seeks, but return TRUE, aggregator then waits forever
for the flushing events.
Fixes#276
When passing "sink_%d" twice to aggregator before it would create two
pads called "sink_0", because it failed to parse "%d" as integer and
used 0 instead then.
Instead validate that parsing was actually successful and also don't
even try to parse if the requested pad name contains a '%'.
strcmp() does not allow the arguments to be NULL, but g_strcmp0()
does, so document that we use g_strcmp0() so that people don't need to
worry about that.
At the moment, we can only use crank if the pending entry is in the
future. This patch leaves the clock time to the same point if the
pending entry was in the past. This still execute a single entry. This
will be needed for the jitterbuffer, since as soon as we stop waking up
the jitterbuffer when the timer is reschedule later, we may endup with
such case in the unit tests.
Related to #608
By only having it on sinkpad-creation, it is racy to write a test
with a sometimes-pad (like a demuxer) that you want to pull from, having
the pull wait until the pad arrives and the buffer can be produced.
For the query function there's a risk that the function may be called
after the harness has been teared down. Since the function accesses a
pointer to the harness via the pad's data, the harness must protect
itself against this.
Event and chain function is also handled for constistency, although
they don't have the same problem since the gstpad.c checks whether the
pad is flushing before calling these.
This was a misguided effort to try and guarantee the buffers of
the sink pads would not change during aggregate, when an upstream
branch is seeked independently, however this is simply incorrect
as downstream has not necessarily been flushed, or the aggregate
function might be waiting to receive buffers on other pads.
In !159 , we switched to sending flush_start ourselves from the
do_seek implementation. If no flushing seek successfully made its
way upstream, we need to send flush_stop ourselves as well.
Releasing a GRecMutex from a different thread is undefined
behaviour.
There should be no reason to hold the stream lock from the
moment aggregator receives a flush_start until it receives
the last flush_stop: the source pad task is stopped, and can
only be restarted once the last flush_stop has arrived.
I can only speculate as to the reason why this was done,
as it was that way since the original commit. My best
guess is that aggregator originally didn't marshall events
and queries to the aggregate thread, and this somehow
helped work around this.
Instead of tracking "pending_flush_*" on the pads and the
aggregator, we now simply track the last seqnum for flush start
and flush stop events on the pads, and use it to determine whether
we should enter or exit our flushing state.
See https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/977
Since we started depending on GLib 2.44, we can be sure this macro is
defined (it will be a no-op on compilers that don't support it). For
plugins we should just start using `G_DECLARE_FINAL_TYPE` which means
we no longer need the macro there, but for most types in core we don't
want to break ABI, which means it's better to just keep it like it is
(and use the `#ifdef` instead).
Not that it matters, since we don't check the return value
anyway. Unclear why the aggregator pad flush function should
have a return value at all really, and perhaps it should be
called reset anyway. Spotted by dv on irc.
Another helper to navigate a pipeline. It makes it possible to easily
access the pads of an element:
(gdb) print $gst_element_pad(basesink, "sink")
$1 = 0x7fffe80770f0 [GstPad|sink]
This add the different timestamps for segment events:
(gdb) gst-print pad
SrcPad(src, push) {
events:
[...]
segment: time
rate: 1.1
start: 0:03:08.449753330
time: 0:03:08.449753330
position: 0:03:08.449753330
duration: 0:12:14.166687500
[...]
}
It shows a simple tree of all elements in pipeline.
As with gst-dot, the toplevel bin is found from any element of the
pipeline:
(gdb) gst-pipeline-tree bsink
playbin
inputselector1
inputselector0
uridecodebin0
queue2-0
decodebin0
avdec_aac0
aacparse0
vaapidecodebin0
vaapipostproc0
capsfilter1
vaapi-queue
vaapidecode0
capsfilter0
h264parse0
multiqueue0
matroskademux0
typefind
typefindelement0
source
playsink
abin
aconv
resample
conv
identity
aqueue
pulsesink0
vbin
vconv
scale
conv
identity
vqueue
vaapisink0
vdbin
deinterlace
vdconv
audiotee
streamsynchronizer0
This simplifies navigating in a GStreamer pipeline, e.g.
(gdb) print $gst_bin_get($gst_pipeline(pad), "matroskademux0")
$1 = 0x7fffe81b4050 [GstMatroskaDemux|matroskademux0]
For elements, this adds all child elements, the state and base/start time:
(gdb) gst-print pipeline
0x5555556ebd20 "pipeline0"
GstPipeline(pipeline0) {
children:
fakesink0
queue0
videotestsrc0
state: PLAYING
base_time: +2:54:36.892581150
start_time: 0:00:00.000000000
}
For pads, this adds the peer pads and the current task state and the
offset (if not zero):
(gdb) gst-print pad
SrcGhostPad(src, push) {
events:
[...]
peer: vaapisink0:sink
inner peer: scale:src
}
(gdb) gst-print pad
SrcPad(src, push) {
events:
[...]
peer: queue0:sink
task: STARTED
offset: 30000000 [+0:00:00.030000000]
}
* Making sure that `static inline` function are in the GIR (by first
defining them, and make sure to mark as skiped)
* Do not try to link to unexisting symbols
* Also generate GIR information about gst_tracers
The original version of the patch used glib-2.0 but that was later changed
to gstreamer-1.0 for autotools. The meson file was forgotten.
Fix the path to match the one used in libgstreamer-gdb.py.in.
It's possible that setcap is installed, but the libcap headers/libs aren't (e.g.
during cross compilation, when you have the program installed for the host,
but need the headers of the target). Also removes the need to manually check
for the libcap headers.
Internal gst_net_utils_set_socket_dscp renamed and turned into external
function. Similar functionality exists in e.g. multidupsink, which could
instead use this one.