gstreamer/subprojects
Alicia Boya García 9b0fad5f0c appsink: Fix race condition on caps handling
Background:

Whenever a caps event is received by appsink, the caps are stored in the
same internal queue as buffers. Only when enough buffers have been
popped from the queue to reach the caps, `priv->sample` gets its caps
updated to match, so that they are correct for the following buffers.

Note that as far as upstream elements are concerned, the caps of appsink
are updated immediately when the CAPS event is sent. Samples pulled from
appsink retain the old caps until a later buffer -- one that was sent by
upstream elements after the new caps -- is pulled.

The race condition:

When a flush is received, appsink clears the entire internal queue. The
caps of `priv->sample` are not updated as part of this process, and
instead remain as those of the sample that was last pulled by the user.

This leaves open a race condition where:
1. Upstream sends a new caps event, and possibly some buffers for the
   new caps.
2. Upstream sends a flush (possibly from a different thread).
3. Upstream sends a new buffer for the new caps. Since as far as
   upstream is concerned, appsink caps are the new caps already, no new
   CAPS event is sent.
4. The appsink user pulls a sample, having not pulled before enough
   samples to reach the buffers sent in step 1.

Bug: the pulled sample has the old caps instead of the new caps.

Fixing the race condition:

To avoid this problem, when a buffer is received after a flush,
`priv->sample`'s caps should be updated with the current caps before the
buffer is added to the internal queue.

Interestingly, before this patch, appsink already had code for this, in
gst_app_sink_render_common():

    /* queue holding caps event might have been FLUSHed,
     * but caps state still present in pad caps */
    if (G_UNLIKELY (!priv->last_caps &&
            gst_pad_has_current_caps (GST_BASE_SINK_PAD (psink)))) {
      priv->last_caps = gst_pad_get_current_caps (GST_BASE_SINK_PAD (psink));
      gst_sample_set_caps (priv->sample, priv->last_caps);
      GST_DEBUG_OBJECT (appsink, "activating pad caps %" GST_PTR_FORMAT,
          priv->last_caps);
    }

This code assumes `priv->last_caps` is reset when a flush is received,
which makes sense, but unfortunately, there was no code in the flush
code path resetting it.

This patch adds such code, therefore fixing the race condition. A unit
test demonstrating the bug and testing its behavior with the fix has
also been added.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2442>
2022-05-18 00:05:34 +01:00
..
gst-devtools Back to development 2022-05-03 00:55:58 +01:00
gst-docs Back to development 2022-05-03 00:55:58 +01:00
gst-editing-services Back to development 2022-05-03 00:55:58 +01:00
gst-examples Back to development 2022-05-03 00:55:58 +01:00
gst-integration-testsuites Back to development 2022-05-03 00:55:58 +01:00
gst-libav Back to development 2022-05-03 00:55:58 +01:00
gst-omx Back to development 2022-05-03 00:55:58 +01:00
gst-plugins-bad pcapparse: Set timestamp in DTS, not PTS 2022-05-16 11:16:43 +02:00
gst-plugins-base appsink: Fix race condition on caps handling 2022-05-18 00:05:34 +01:00
gst-plugins-good vpxenc: fix crash if encoder produces unmatching ts 2022-05-17 11:12:43 +02:00
gst-plugins-ugly Back to development 2022-05-03 00:55:58 +01:00
gst-python Back to development 2022-05-03 00:55:58 +01:00
gst-rtsp-server Back to development 2022-05-03 00:55:58 +01:00
gstreamer aggregator: Don't send multiple caps events with the same caps 2022-05-06 01:19:40 +01:00
gstreamer-sharp Back to development 2022-05-03 00:55:58 +01:00
gstreamer-vaapi Back to development 2022-05-03 00:55:58 +01:00
macos-bison-binary New subproject macos-bison-binary to provide bison on macOS 2021-08-28 23:44:52 +05:30
win-flex-bison-binaries win-flex-bison: Use gstreamer mirror as primary source 2020-01-18 17:54:48 +05:30
win-nasm win-nasm: Use gstreamer mirror as primary source 2020-01-18 17:54:48 +05:30
avtp.wrap Revert "Revert "Add libavtp wrap file"" 2020-06-30 15:47:18 -07:00
bindinator.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
cairo.wrap meson: Build cairo subproject when unavailable on the system 2022-01-21 06:34:33 +00:00
dav1d.wrap Add dav1d wrap file 2020-05-02 09:55:12 +00:00
dssim.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
dv.wrap subprojects: add libdv wrap 2021-01-14 19:16:01 +00:00
expat.wrap meson: Update expat.wrap for MSVC fix 2020-11-05 13:09:46 +05:30
fdk-aac.wrap subprojects: fdk-aac: add fallback_url 2021-10-28 23:29:27 +00:00
FFmpeg.wrap wraps:ffmpeg: Move to 4.4 2021-10-15 02:32:40 +00:00
fontconfig.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
freetype2.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
fribidi.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
gl-headers.wrap Move files from gst-plugins-base into the "subprojects/gst-plugins-base/" subdir 2021-09-24 16:13:26 -03:00
glib-networking.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
glib.wrap meson: Update subprojects to fix warnings 2022-01-25 14:25:19 +05:30
graphene.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
gst-plugins-rs.wrap subprojects: Switch gst-plugins-rs.wrap to the 0.8 branch for 1.20 2022-02-20 14:25:40 +00:00
gtk-sharp.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
harfbuzz.wrap harfbuzz.wrap: Use the latest tag instead of tip of git 2021-07-02 17:08:48 +03:00
json-glib.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
lame.wrap subprojects/lame: Update to latest wrap 2022-01-28 02:01:39 +05:30
libdrm.wrap meson: Update subprojects to fix warnings 2022-01-25 14:25:19 +05:30
libffi.wrap
libjpeg-turbo.wrap subprojects: Bump libjpeg-turbo version to 2.1.0-2 for x86 MSVC build 2021-08-04 19:22:30 +09:00
libmicrodns.wrap subprojects: libmicrodns: pin to 0.1.2 release 2020-07-07 15:23:29 +01:00
libnice.wrap subprojects: Update libnice to 0.1.19 2022-05-04 14:04:09 +01:00
libopenjp2.wrap wrap: libopenjp2: use patch version 7 2021-10-22 19:47:27 +00:00
libpng.wrap subprojects/libpng: Update to latest wrap file 2022-01-28 02:01:39 +05:30
libpsl.wrap libpsl.wrap: pin to 0.21.1 tag 2020-10-26 12:13:12 +00:00
libsoup.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
libwpe.wrap subprojects: Update libwpe and wpebackend-fdo for fallback support 2020-10-12 12:29:01 +00:00
libxml2.wrap libxml2: update wrap path to 2.9.7-6 2020-02-19 13:45:52 +01:00
ogg.wrap subprojects: Update ogg and vorbis wraps 2021-10-19 17:42:21 +00:00
openh264.wrap openh264: update to v2.1.1 2020-05-31 11:11:18 +01:00
opus.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
orc.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
pango.wrap subprojects: pin pango wrap to tag 2021-08-08 19:42:24 +01:00
pcre.wrap subprojects/pcre: Add the wrap so it's cached in the image 2022-01-28 02:01:39 +05:30
pixman.wrap meson: Update subprojects to fix warnings 2022-01-25 14:25:19 +05:30
proxy-libintl.wrap subprojects: proxy-libintl: fix push-url 2019-08-14 18:51:43 +01:00
pycairo.wrap {pygobject,pycairo}.wrap: point to stable refs 2020-09-15 15:51:42 +03:00
pygobject.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
sqlite3.wrap Update to sqlite3 from wrapdb 2021-08-24 20:52:06 +00:00
vorbis.wrap subprojects: Update ogg and vorbis wraps 2021-10-19 17:42:21 +00:00
webrtc-audio-processing.wrap Pin all wrap files to closest tag or commit sha1 2021-10-14 22:34:49 +00:00
wpebackend-fdo.wrap subprojects: Update libwpe and wpebackend-fdo for fallback support 2020-10-12 12:29:01 +00:00
x264.wrap x264: update to latest stable 160.3011 2020-07-30 15:52:38 +01:00
zlib.wrap meson: Update zlib.wrap to use wrapdb instead of github fork 2021-01-13 12:55:06 +00:00