If the first buffers have no timestamp then the sink position would be
initialized to 0. The source pad might output this buffer, which would then
initialize the source position to 0 too.
Afterwards two buffers with a valid but huge timestamp might arrive before any
of them are output on the source pad. The first one would set the sink position
to a huge value, the second one would notice that the difference between the
huge value and 0 is certainly larger than max-size-time and consider the queue
as full.
Instead, simply don't update the times from buffers without timestamps and
assume whatever was set before is still valid, i.e. the buffer has the same
timestamp as the previous one.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7075>
We were storing the probe id in a different structure (DecodebinOutputStream)
than the pad it is targetting (which is in MultiQueueSlot).
The problem is that when re-targetting outputs (to a different slot)... we would
end up having an invalid probe id, or not have a reference to an existing one.
Instead, store the probe id in the same structure as the pad it's targetting
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7074>
According to the SPEC:
The frame id numbers (represented in display_frame_id, current_frame_id,
and RefFrameId[ i ]) are not needed by the decoding process, but allow
decoders to spot when frames have been missed and take an appropriate action.
So we should just print out warning and should not return error in parser when
mismatching. The decoder itself is already robust to handle the reference missing.
Fixes#3622
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7052>
Specify "layout" field in src template to make sure it's
set and gets fixated properly if the downstream element
supports both interleaved and non-interleaved caps.
Fixes
gst_pad_set_caps: assertion 'caps != NULL && gst_caps_is_fixed (caps)' failed
critical with e.g.
gst-launch-1.0 rtpdtmfsrc ! rtpdtmfdepay ! audioconvert ! fakesink
Not that the layout really matters in our case since we always
output mono anyway, but non-interleaved requires adding AudioMeta,
so this is the easiest fix.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7048>
This was already being used in handle_frame() for errors that happen when queueing a frame for decoding,
let's do the same when a frame is flagged with an error in the output callback.
From quick testing, this makes seeking more reliable (previously, it would sometimes cause a decoding error
and shut the whole decoder down due to GST_FLOW_ERROR).
Also manually sets the max error count to actually stop processing if too many errors occur.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7044>
ReferenceMissingErr is not critical and the simplest solution is to just ignore it. The frame has
the FrameDropped flag set when it occurs, so we can just drop it as usual.
BadDataErr is also not immediately critical, but in its case let's set the ERROR flag,
so the output loop can use GST_VIDEO_DECODER_ERROR to count and error out if it happens too many times.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7044>
Upon fatal errors the loop function will first post an error message
then push out an EOS event.
An application may react immediately to the error message by setting the
state of the pipeline to NULL, meaning by the time we push out the EOS
event PAUSED_TO_READY may have reset the seek seqnum to -1.
While this is harmless, the assertion when setting an invalid seqnum
isn't tidy, fix this by simply not resetting to INVALID as it serves no
practical purpose and the next READY_TO_PAUSED will select a new seqnum
anyway.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7034>
Certain V4L2 drivers can report that a video receiver is seeing
some signal, but that it is unable to synchronize to it. IOW: the driver
can sometimes report V4L2_IN_ST_NO_SYNC and not report V4L2_IN_ST_NO_SIGNAL.
In particular, I've seen the tc358743 (HDMI-to-CSI2 converter) driver
sometimes report this when deployed to a fleet of embedded Raspberry Pis.
The relevant kernel code is in [1]. The video output is not practically
usable when V4L2_IN_ST_NO_SYNC is reported (only visually corrupted frames,
sometimes with random "snow", are received). I assume that this happens when
either the HDMI cable is poorly plugged in or damaged or when a CSI2 FFC
cable is used and is damaged.
The change in this commit is useful for detecting this working-but-not-really
condition in application code. Applications already listening for the "Signal lost"
message will gain the ability to handle this condition.
There seem to be more V4L2 error flags like this, see [2]. However, I do not
have practical experience with them and adding only V4L2_IN_ST_NO_SYNC seems
like a safer option.
[1]: https://github.com/raspberrypi/linux/blob/be8498ee21aa/drivers/media/i2c/tc358743.c#L1534
[2]: https://www.kernel.org/doc/html/v6.6/userspace-api/media/v4l/vidioc-enuminput.html
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7027>
Musl does not implement GNU basename and have fixed a bug where the
prototype was leaked into string.h [1], which resullts in compile errors
with GCC-14 and Clang-17+
| sys/uvcgadget/configfs.c:262:21: error: call to undeclared function 'basename'
ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
| 262 | const char *v = basename (globbuf.gl_pathv[i]);
| | ^
Use glib function instead makes it portable across musl and glibc on
linux
[1] https://git.musl-libc.org/cgit/musl/commit/?id=725e17ed6dff4d0cd22487bb64470881e86a92e7a
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7028>
This fixes a regression introduced by 6c4f52ea20
There are cases where the input stream will be push-based, time-segment and not
have a collection nor caps. This means the event-based checks are not sufficient
to decide when/where to plug in a identity or parsebin to process the input.
For those corner cases we setup a buffer probe to ensure we always end up with
at least a parsebin
Fixes#3609
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7018>
When dealing with push-based inputs, we are now delaying the creation of
parsebin/identity until we get all pre-buffer events.
We therefore can simplify the handling of new pads being linked and only have to
check if upstream can handle pull-based or not.
Avoids creating parsebin for parsed upstream data altogether
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6995>
When we are dealing with parsed inputs (i.e. using identity), we need to ensure
that we have a valid stream collection (and therefore DBCollection) before
anything flows dowsntream.
In those cases, we hold onto those events until we get such a collection.
Fixes#3356
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7002>
This commit separates collection and selections into a new separate structure:
DecodebinCollection.
This provides a much cleaner/saner way of dealing with collections being
updated, gapless playback, etc...
There is now a list of DecodebinCollection in flight, of which two are special:
* input_collection, the currently inputted/merged collection
* output_collection, the currently active collection on the output of multiqueue
Handling GST_EVENT_SELECT_STREAMS is split, by looking for the collection to
which it applies. And the requested streams are stored in it. IIF that
collection is output_collection we can do the switch, else it will be updated
when it becomes active.
Detecting which collection/selection is active is done by looking at the
GST_EVENT_STREAM_START on the output of the multiqueue.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7002>
* Move the handling of GST_EVENT_STREAM_START on a slot to a separate function
* There was a lot of usage of `gst_stream_get_stream_id()` for the slot
active_stream. Cache that instead of constantly querying it.
* Rename the variables in `handle_stream_switch()` to be clearer
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7002>
* Centralize associating an output to a slot in one function, including properly
resetting those fields
* Rename functions to be more explicit
* Move code to "reset" an output stream into a dedicated function (will be used
later)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7002>
* Rename the function names to be clearer, with prefixes
* Pass the input (or stream) directly where appropriate
* Document usage, inputs, ownership
* Rename variables for clarity where applicable
* Avoid double lock/unlock if callee can handle it directly
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7002>
Simplify its usage by having it directly create the message if the collection
changed. This is what caller were always doing and avoids releasing selection
locks yet-another-time
Also use it in more places to avoid code repetition
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7002>
Not all GPUs can support arbitrary offset of
D3D12_PLACED_SUBRESOURCE_FOOTPRINT when copying GPU memory between
texture and buffer. Instead of calculating size/offset per plane,
calculate the entire size and offsets at once.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6973>
Some servers might not provide 100% matching PDT when doing updates, or accross
variants. This would cause the code matching segments using PDT to fail if the
segment PDT was 1 microsecond (or whatever small value) before the candidate
segment. And would pick the (wrong) following segment as the matching one.
In order to be more tolerant when matching, we instead check whether the
candidate segment is within the first segment of the segment we are trying to
match.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6961>
If we end up with a segment with an internal time that varies from the supposed
one, this could be for two reasons:
* We guess-timated the wrong segment to go to when advancing or switching
variants. In that case we try to find the actual segment to go to (just before
this change).
* There was a complete playlist change (for whatever reason) and we can't find a
replacement. In that case we want to carry on playback from this position but
need to remember that we moved (by setting the stream to DISCONT, and
resetting the new mapping).
Fixes playback on several broken stream
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6961>
Since the default value of `m3u8->discont_sequence` (before parsing of the
playlist data) was 0 .. we would never properly detect the presence of that
field if it was present with a value of 0.
This would later on cause havoc in playlist synchronization where we would
assume it didn't have a discontinuity sequence specified (whereas it did, and it
was 0).
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6961>
A lot of streams will do a poor job of estimating proper duration of fragments
in the playlist, but over several fragments have it correct.
Instead of constantly trying to realign the estimated stream time, allow for a
more realistic tolerance of 3-4 video frames
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6961>
When updating playlists, we want to know whether the updated playlist is
continuous with the previous one. That is : if we advance, will the next
fragment need to have the DISCONT buffer set on it or not.
If that happens (because we switched variants, or the playlist all of a sudden
changed) we remember that there is a pending discont for the next fragment. That
will be used and resetted the next time we get the fragment information.
Previously this was only partially done. And it was racy because it was set
directly on `GstAdaptiveDemux2Stream->discont` when a playlist was updated,
instead of when the next fragment was prepared.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6961>
When dealing with live streams, the function was assuming that all segments of
the playlist had valid stream_time. But that isn't TRUE, for example in the case
of failing to synchronize playlists.
Fixes losing sync due to not being able to match playlist on updates
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6961>
The name is already passed via the signal parameters so it doesn't have
to be retrieved again via GstObject API, which would crash on other
GObjects. Child proxy child objects can be any kind of GObject and the
code here otherwise handles this correctly already.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6951>
On various 32 bit systems, time_t is actually 64 bits while long is
still only 32 bits. The macro would wrongly trigger its assertion in
this case if a value with more than 68 years worth of seconds is
converted.
Examples are various newer 32 bit platforms and old ones that are
compiled with -D_TIME_BITS=64.
Also statically assert that time_t is either 32 or 64 bits. Other values
might need adjustments in the macro.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6919>
The prime_fds for multi planes may be the same. For example, on Intel's
platform, the NV12 surface may have the same FD for the plane0 and the
plane1. Then, the DRM_IOCTL_GEM_CLOSE will close the same handle twice
and get an "Invalid argument 22" error the second time.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6916>
To simplify the description, I'm assuming we only have two streams: video and audio.
For the video stream, we have the following events :
- STREAM_START => stream->wait set to true
- NEW_SEGMENT(1) => blocked waiting in gst_stream_synchronizer_wait
- FLUSH_START => unblocked
- FLUSH_STOP => stream->wait reset to false
- NEW_SEGMENT(2) => not waiting, since stream->wait is false
Then for the audio stream, we have the following events :
- STREAM_START => stream->wait set to true
- NEW_SEGMENT(2) => blocked waiting in gst_stream_synchronizer_wait for ever.
Note: The first NEW_SEGMENT event and the FLUSH_START, FLUSH_STOP events of the audio stream
are dropped before being received by the streamsynchronizer element, because the decodebin audio pad src
is not yet linked to the playsink audio pad sink.
To fix this deadlock, we don't reset stream->wait to false in the FLUSH_STOP event when it is not
waiting for the EOS of the other streams.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6887>
The FORCE_KEYFRAME frame which has GST_VIDEO_CODEC_FRAME_FLAG_FORCE_KEYFRAME
bit set should be the sync point. So we should let it be an IDR frame to begin
a new GOP, rather than just promote it to an I frame.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6857>
The FORCE_KEYFRAME frame which has GST_VIDEO_CODEC_FRAME_FLAG_FORCE_KEYFRAME
bit set should be the sync point. So we should let it be an IDR frame to begin
a new GOP, rather than just promote it to an I frame.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6857>
This mirrors the behaviour in vp8enc / vp9enc and is generally more
useful than using any framerate from the caps as it provides some degree
of accuracy if the stream doesn't have timestamps perfectly according to
the framerate.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6909>
Turns out AudioConvertHostTimeToNanos and AudioGetCurrentHostTime are macOS-only APIs, which prevents apps using
GStreamer on iOS from being accepted into App Store.
This commit replaces those functions with a manual version of what they do - mach_absolute_time() for the current time,
and data from mach_timebase_info() at the beginning to convert host timestamps to nanoseconds.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6899>
_get_osfhandle() expects valid fd and CRT will abort program
if given paramerter is invalid. The fd can be invalidated
in various way, file was deleted by other process after
we open a file. To avoid it, our own exception
handler must be installed so that _get_osfhandle() can return
INVALID_HANDLE_VALUE if fd is invalid.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6879>
If the muxer times out because of the latency deadline it can happen
that some pads have no caps yet. In that case skip creation of streams
for these pads and create updated section tables once the first buffer
arrives later.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6859>
This makes sure that for sparse streams (KLV, DVB subtitles, ...) the
muxer does not wait until the next buffer is available for them but
times out on the latency deadline and outputs data.
For non-live pipelines it will still be necessary for upstream to
correctly produce gap events for sparse streams.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6859>
__STDC_NO_ATOMICS doesn't seem to exist. In fact the only compiler
I've found that sets any of those is msvc, but it sets
__STDC_NO_ATOMICS__, not __STDC_NO_ATOMICS.
__STDC_NO_ATOMICS__ is the one documented by C11 standard.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6856>
This fixes the code regarding dropping "ghost frames", that is to say input
frames which ended up not producing any decoded frame.
The iteration itself makes sense.. but it was stopping at the "input" frame and
not the decoded frame we just got back.
When dealing with I-frame codecs, ffmpeg will decode frames in separate frames,
so there is no guarantee that they are decoding in order.
Fixes playback issues with such codecs
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6845>
There's nothing requiring <= 64 channels except for getting the reorder
map and creating a channel mixing matrix, but those won't be possible to
call anyway as channel positions can only express up to 64 channels.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6828>
Certain V4L2 fourccs don't (yet) have DRM counter parts, in which case
we can't create DMA_DRM caps for them. This is usually the case for
specific tilings, which are represented as modifiers for DMA formats.
While using these tilings is generally preferable - because of e.g.
lower memory usage - it can result in additional conversion steps when
interacting with DMA based APIs such as GL, Vulkan or KMS. In such cases
using a DMA compatible format usually ends up being the better option.
Before the addition of DMA_DRM caps, this was what playbin3 ended up
requesting in various cases - e.g. prefering NV12 over NV12_4L4 - but
the addition of DMA_DRM caps seems to confuse the selection logic.
As a simple and quite robust solution, assume that peers supporting
DMA_DRM caps always prefer these and reorder the caps accordingly.
In the future we plan to have a translation layer for cases where
there is a matching fourcc+modifier pair for a V4L2 fourcc, ensuring
optimal results.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6824>
Doing it in gst_play_new() means that bindings that directly call
g_object_new() with the GType wouldn't end up initializing both.
This affects at least the Python and GJS bindings.
gst_init() is nonetheless only called from gst_play_new() once because
calling it from class_init would likely lead to problems as that's
called from somewhere in the middle of GObject.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6821>
Don't add an extra ref if non-floating as that ref will never be
unreffed.
gst_bin_add() is transfer floating (alias to transfer none).
Fixes a leak when a non-floating ref was provided as a return value in
the request-aux-sender signal.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6809>
The h26xdecoder 'stop' method was not called
as the vulkan h26x class rewires the video decoder
'stop' base method to its own one.
It was causing some memory leaks such as dangling parser
and dpb in h26xdecoder base class.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6787>
Modifying the `avoid-reencoding` property of `encodebin` could potentially cause
it to reconfigure itself, in which case the source pad will be removed and then
re-added.
Therefore set that property *before* attempting to link to that pad.
Fixes smart-render
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6785>
when pipline is
glvideomixerelement->glcolorconvertelement->gldownloadelement and
glcolorconvertelement is not passthrough, the gl bufferpool between
glvideomixerelement and glcolorconvertelement will not add gl sync meta
during allocating buffer. This will cause that glcolorconvert's inbuf
has no sync meta to wait for.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6784>
1. The PTS of all frames should not be changed.
2. Just update the DTS based on the PTS. For the frame which is not
reordered, the DTS is equal to PTS. For frame which is reordered,
the DTS is equal to previous DTS. For example:
Input: F0[D0, P0] -- F1[D1, P1] -- F2[D2, P2] -- F3[D3, P3]
Output: F0[I, D0, P0] -- F3[P, D0, P3] -- F1[B, D1, P1] -- F2[B, D2, P2]
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6764>
1. The PTS of all frames should not be changed.
2. Just update the DTS based on the PTS. For the frame which is not
reordered, the DTS is equal to PTS. For frame which is reordered,
the DTS is equal to previous DTS. For example:
Input: F0[D0, P0] -- F1[D1, P1] -- F2[D2, P2] -- F3[D3, P3]
Output: F0[I, D0, P0] -- F3[P, D0, P3] -- F1[B, D1, P1] -- F2[B, D2, P2]
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6764>
Valgrind complains about uninitialized memory used in an ioctl
Syscall param ioctl(VKI_V4L2_G_TUNER).reserved points to uninitialised byte(s)
at 0x719294F: ioctl (ioctl.c:36)
by 0x3126A817: gst_v4l2_fill_lists (v4l2_calls.c:185)
by 0x3126A817: gst_v4l2_open (v4l2_calls.c:589)
by 0x3123F1C2: gst_v4l2_device_provider_probe_device (gstv4l2deviceprovider.c:122)
by 0x3123F648: gst_v4l2_device_provider_device_from_udev (gstv4l2deviceprovider.c:301)
by 0x3123F998: provider_thread (gstv4l2deviceprovider.c:395)
by 0x796FA50: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.7200.4)
by 0x710CAC2: start_thread (pthread_create.c:442)
by 0x719DA03: clone (clone.S:100)
Address 0x44008a34 is on thread 11's stack
in frame #1, created by gst_v4l2_open (v4l2_calls.c:524)
Uninitialised value was created by a stack allocation
at 0x3126A024: gst_v4l2_open (v4l2_calls.c:524)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6761>
Neither LIBDIR nor LIBPL are set with the native windows Python
(unlike MSYS2), so we need to use `prefix` which takes us to the
rootdir of the Python installation.
The name is also different: it's python312.dll, not python3.12.dll.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6748>
`python.get_variable('FOO', [])` becomes `python.get_variable('FOO')`
due to how Meson treats empty arrays in arguments, which breaks the
fallback feature of get_variable().
So we need to actually check whether the variable exists before trying
to fetch it.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6748>