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
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.
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.
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 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 '%'.
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