Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package gstreamer-plugins-good for openSUSE:Factory checked in at 2025-07-03 12:09:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gstreamer-plugins-good (Old) and /work/SRC/openSUSE:Factory/.gstreamer-plugins-good.new.1903 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gstreamer-plugins-good" Thu Jul 3 12:09:59 2025 rev:119 rq:1289973 version:1.26.3 Changes: -------- --- /work/SRC/openSUSE:Factory/gstreamer-plugins-good/gstreamer-plugins-good.changes 2025-06-06 22:34:51.496442697 +0200 +++ /work/SRC/openSUSE:Factory/.gstreamer-plugins-good.new.1903/gstreamer-plugins-good.changes 2025-07-03 12:11:58.397463190 +0200 @@ -1,0 +2,24 @@ +Tue Jul 1 19:57:02 UTC 2025 - Bjørn Lie <bjorn....@gmail.com> + +- Update to version 1.26.3: + + aacparse: Fix counting audio channels in program_config_element + + adaptivedemux2: free cancellable when freeing transfer task + + dashdemux2: Fix seeking in a stream with gaps + + decodebin wavparse cannot pull header + + imagefreeze: fix not negotiate log when stop + + osxvideosink: Use gst_pad_push_event() and post navigation + messages + + qml6glsink: Allow configuring if the item will consume input + events + + qtmux: Update chunk offsets when converting stco to co64 with + faststart + + splitmuxsink: Only send closed message once per open fragment + + rtph265depay: CRA_NUT can also start an (open) GOP + + rtph265depay: fix codec_data generation + + rtspsrc: Don't emit error during close if server is EOF + + twcc: Fix reference timestamp wrapping (again) + + v4l2: Fix possible internal pool leak + + v4l2object: Add support for colorimetry bt2100-pq and 1:4:5:3 + + wavparse: Don't error out always when parsing acid chunks + +------------------------------------------------------------------- Old: ---- gst-plugins-good-1.26.2.obscpio New: ---- gst-plugins-good-1.26.3.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gstreamer-plugins-good.spec ++++++ --- /var/tmp/diff_new_pack.hMJPNa/_old 2025-07-03 12:12:00.221538676 +0200 +++ /var/tmp/diff_new_pack.hMJPNa/_new 2025-07-03 12:12:00.225538842 +0200 @@ -33,7 +33,7 @@ %endif Name: gstreamer-plugins-good -Version: 1.26.2 +Version: 1.26.3 Release: 0 Summary: GStreamer Streaming-Media Framework Plug-Ins License: LGPL-2.1-or-later ++++++ _service ++++++ --- /var/tmp/diff_new_pack.hMJPNa/_old 2025-07-03 12:12:00.305542153 +0200 +++ /var/tmp/diff_new_pack.hMJPNa/_new 2025-07-03 12:12:00.309542319 +0200 @@ -5,7 +5,7 @@ <param name="url">https://gitlab.freedesktop.org/gstreamer/gstreamer.git</param> <param name="subdir">subprojects/gst-plugins-good</param> <param name="filename">gst-plugins-good</param> - <param name="revision">1.26.2</param> + <param name="revision">1.26.3</param> <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param> <param name="versionrewrite-pattern">v?(.*)\+0</param> <param name="versionrewrite-replacement">\1</param> ++++++ gst-plugins-good-1.26.2.obscpio -> gst-plugins-good-1.26.3.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/NEWS new/gst-plugins-good-1.26.3/NEWS --- old/gst-plugins-good-1.26.2/NEWS 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/NEWS 2025-06-26 22:25:24.000000000 +0200 @@ -1809,6 +1809,213 @@ - List of Merge Requests applied in 1.26.2 - List of Issues fixed in 1.26.2 +1.26.3 + +The third 1.26 bug-fix release (1.26.3) was released on 26 June 2025. + +This release only contains bugfixes including some important playback fixes, and it should be safe to update from 1.26.x. + +Highlighted bugfixes in 1.26.3 + +- Security fix for the H.266 video parser +- Fix regression for WAV files with acid chunks +- Fix high memory consumption caused by a text handling regression in uridecodebin3 and playbin3 +- Fix panic on late GOP in fragmented MP4 muxer +- Closed caption conversion, rendering and muxing improvements +- Decklink video sink preroll frame rendering and clock drift handling fixes +- MPEG-TS demuxing and muxing fixes +- MP4 muxer fixes for creating very large files with faststart support +- New thread-sharing 1:N inter source and sink elements, and a ts-rtpdtmfsrc +- New speech synthesis element around ElevenLabs API +- RTP H.265 depayloader fixes and improvements, as well as TWCC and GCC congestion control fixes +- Seeking improvements in DASH client for streams with gaps +- WebRTC sink and source fixes and enhancements, including to LiveKit and WHIP signallers +- The macOS osxvideosink now posts navigation messages +- QtQML6GL video sink input event handling improvements +- Overhaul detection of hardware-accelerated video codecs on Android +- Video4Linux capture source fixes and support for BT.2100 PQ and 1:4:5:3 colorimetry +- Vulkan buffer upload and memory handling regression fixes +- gst-python: fix various regressions introduced in 1.26.2 +- cerbero: fix text relocation issues on 32-bit Android and fix broken VisualStudio VC templates +- packages: ship pbtypes plugin and update openssl to 3.5.0 LTS +- Various bug fixes, build fixes, memory leak fixes, and other stability and reliability improvements + +gstreamer + +- aggregator: Do not set event seqnum to INVALID +- baseparse: test: Fix race on test start +- pad: Only remove TAG events on STREAM_START if the stream-id actually changes +- utils: Mark times array as static to avoid symbol conflict with the POSIX function +- vecdeque: Use correct index type gst_vec_deque_drop_struct() + +gst-plugins-base + +- GstAudioAggregator: fix structure unref in peek_next_sample() +- audioconvert: Fix setting mix-matrix when input caps changes +- encodebasebin: Duplicate encoding profile in property setter +- gl: simplify private gst_gl_gst_meta_api_type_tags_contain_only() +- osxvideosink: Use gst_pad_push_event() and post navigation messages +- playsink: Fix race condition in stream synchronizer pad cleanup during state changes +- python: Fix pulling events from appsink +- streamsynchronizer: Consider streams having received stream-start as waiting +- urisourcebin: Text tracks are no longer set as sparse stream in urisourcebin’s multiqueue + +gst-plugins-good + +- aacparse: Fix counting audio channels in program_config_element +- adaptivedemux2: free cancellable when freeing transfer task +- dashdemux2: Fix seeking in a stream with gaps +- decodebin wavparse cannot pull header +- imagefreeze: fix not negotiate log when stop +- osxvideosink: Use gst_pad_push_event() and post navigation messages +- qml6glsink: Allow configuring if the item will consume input events +- qtmux: Update chunk offsets when converting stco to co64 with faststart +- splitmuxsink: Only send closed message once per open fragment +- rtph265depay: CRA_NUT can also start an (open) GOP +- rtph265depay: fix codec_data generation +- rtspsrc: Don’t emit error during close if server is EOF +- twcc: Fix reference timestamp wrapping (again) +- v4l2: Fix possible internal pool leak +- v4l2object: Add support for colorimetry bt2100-pq and 1:4:5:3 +- wavparse: Don’t error out always when parsing acid chunks + +gst-plugins-bad + +- amc: Overhaul hw-accelerated video codecs detection +- bayer2rgb: Fix RGB stride calculation +- d3d12compositor: Fix critical warnings +- dashsink: Fix failing test +- decklink: calculate internal using values closer to the current clock times +- decklinkvideosink: show preroll frame correctly +- decklink: clock synchronization after pause +- h266parser: Fix overflow when parsing subpic_level_info +- lcevcdec: Check for errors after receiving all enhanced and base pictures +- meson: fix building -bad tests with disabled soundtouch +- mpegts: handle MPEG2-TS with KLV metadata safely by preventing out of bounds +- mpegtsmux: Corrections around Teletext handling +- srtsink: Fix header buffer filtering +- transcoder: Fix uritranscodebin reference handling +- tsdemux: Allow access unit parsing failures +- tsdemux: Send new-segment before GAP +- vulkanupload: fix regression for uploading VulkanBuffer +- vulkanupload: fix regression when uploading to single memory multiplaned memory images. +- webrtcbin: disconnect signal ICE handlers on dispose +- {d3d12,d3d11}compositor: Fix negative position handling +- {nv,d3d12,d3d11}decoder: Use interlace info in input caps + +gst-plugins-ugly + +- No changes + +GStreamer Rust plugins + +- Add new speech synthesis element around ElevenLabs API +- cea708mux: fix another WouldOverflow case +- cea708mux: support configuring a limit to how much data will be pending +- cea708overlay: also reset the output size on flush stop +- gcc: handle out of order packets +- fmp4mux: Fix panic on late GOP +- livekit: expose a connection state property +- mp4mux: add taic box +- mp4mux: test the trak structure +- pcap_writer: Make target-property and pad-path properties writable again +- skia: Don’t build skia plugin by default for now +- threadshare: cleanups & usability improvements +- threadshare: sync runtime with latest async-io +- threadshare: fix kqueue reactor +- threadshare: Update to getifaddrs 0.2 +- threadshare: add new thread-sharing inter elements +- threadshare: add a ts-rtpdtmfsrc element +- transcriberbin: fix naming of subtitle pads +- tttocea708: don’t panic if a new service would overflow +- webrtc: android: Update Gradle and migrate to FindGStreamerMobile +- webrtc: add new examples for stream selection over data channel +- webrtcsrc: the webrtcbin get-transceiver index is not mlineindex +- webrtcsrc: send CustomUpstream events over control channel .. +- webrtcsink: Don’t require encoder element for pre-encoded streams +- webrtcsink: Don’t reject caps events if the codec_data changes +- whip: server: pick session-id from the endpoint if specified +- cargo: add config file to force CARGO_NET_GIT_FETCH_WITH_CLI=true +- Cargo.lock, deny: Update dependencies and log duplicated targo-lexicon +- Update windows-sys dependency from “>=0.52, <=0.59” to “>=0.52, <=0.60” +- deny: Add override for windows-sys 0.59 +- deny: Update lints +- cargo_wrapper: Fix backslashes being parsed as escape codes on Windows +- Fixes for Clock: non-optional return types +- Rename relationmeta plugin to analytics + +gst-libav + +- No changes + +gst-rtsp-server + +- rtsp-server: tests: Fix a few memory leaks + +gstreamer-vaapi + +- No changes + +gstreamer-sharp + +- No changes + +gst-python + +This release includes some important regression fixes for the GStreamer Python bindings for regressions introduced in 1.26.2. + +- gst-python/tests: don’t depend on webrtc and rtsp-server +- python: Fix pulling events from appsink and other fixes + +gst-editing-services + +- No changes + +gst-devtools, gst-validate + gst-integration-testsuites + +- validate: More memory leaks +- validate: Valgrind fixes + +gst-examples + +- No changes + +gstreamer-docs + +- No changes + +Development build environment + +- gst-env: Emit a warning about DYLD_LIBRARY_PATH on macOS + +Cerbero build tool and packaging changes in 1.26.3 + +- WiX: fix broken VC templates +- android: Don’t ignore text relocation errors on 32-bit, and error out if any are found +- build: source: handle existing .cargo/config.toml as in plugins-rs +- ci: Detect text relocations when building android examples +- gst-plugins-base: Ship pbtypes +- gst-plugins-base: Fix category of pbtypes +- gst-plugins-rs: Update for relationmeta -> analytics plugin rename +- libsoup.recipe: XML-RPC support was removed before the 3.0 release +- openssl: Update to 3.5.0 LTS + +Contributors to 1.26.3 + +Albert Sjolund, Aleix Pol, Ben Butterworth, Brad Hards, César Alejandro Torrealba Vázquez, Changyong Ahn, Doug Nazar, Edward +Hervey, Elliot Chen, Enrique Ocaña González, François Laignel, Glyn Davies, He Junyan, Jakub Adam, James Cowgill, Jan Alexander +Steffens (heftig), Jan Schmidt, Jochen Henneberg, Johan Sternerup, Julian Bouzas, L. E. Segovia, Loïc Le Page, Mathieu +Duponchelle, Matthew Waters, Nicolas Dufresne, Nirbheek Chauhan, Philippe Normand, Pratik Pachange, Qian Hu (胡骞), Sebastian +Dröge, Seungha Yang, Taruntej Kanakamalla, Théo Maillart, Thibault Saunier, Tim-Philipp Müller, Víctor Manuel Jáquez Leal, +Xavier Claessens, + +… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all! + +List of merge requests and issues fixed in 1.26.3 + +- List of Merge Requests applied in 1.26.3 +- List of Issues fixed in 1.26.3 + Schedule for 1.28 Our next major feature release will be 1.28, and 1.27 will be the unstable development version leading up to the stable 1.28 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/RELEASE new/gst-plugins-good-1.26.3/RELEASE --- old/gst-plugins-good-1.26.2/RELEASE 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/RELEASE 2025-06-26 22:25:24.000000000 +0200 @@ -1,4 +1,4 @@ -This is GStreamer gst-plugins-good 1.26.2. +This is GStreamer gst-plugins-good 1.26.3. The GStreamer team is thrilled to announce a new major feature release of your favourite cross-platform multimedia framework! diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/ext/adaptivedemux2/dash/gstmpdclient.c new/gst-plugins-good-1.26.3/ext/adaptivedemux2/dash/gstmpdclient.c --- old/gst-plugins-good-1.26.2/ext/adaptivedemux2/dash/gstmpdclient.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/ext/adaptivedemux2/dash/gstmpdclient.c 2025-06-26 22:25:24.000000000 +0200 @@ -1710,10 +1710,16 @@ GstClockTime chunk_time; selectedChunk = segment; - repeat_index = - ((ts - segment->start) + - ((GstMediaSegment *) stream->segments->pdata[0])->start) / - segment->duration; + if (ts < segment->start) { + /* Seek time lies in a gap between segments. Continue playing from + * the first repetition of selectedChunk. */ + repeat_index = 0; + } else { + repeat_index = + ((ts - segment->start) + + ((GstMediaSegment *) stream->segments->pdata[0])->start) / + segment->duration; + } chunk_time = segment->start + segment->duration * repeat_index; @@ -1738,7 +1744,7 @@ } } else if (((forward && flags & GST_SEEK_FLAG_SNAP_AFTER) || (!forward && flags & GST_SEEK_FLAG_SNAP_BEFORE)) && - ts != chunk_time) { + ts > chunk_time) { if (repeat_index + 1 < segment->repeat) { repeat_index++; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/ext/adaptivedemux2/downloadhelper.c new/gst-plugins-good-1.26.3/ext/adaptivedemux2/downloadhelper.c --- old/gst-plugins-good-1.26.2/ext/adaptivedemux2/downloadhelper.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/ext/adaptivedemux2/downloadhelper.c 2025-06-26 22:25:24.000000000 +0200 @@ -93,6 +93,7 @@ if (transfer->blocking) g_cond_clear (&transfer->cond); + g_clear_object (&transfer->cancellable); g_object_unref (transfer->msg); g_free (transfer->read_buffer); g_free (transfer); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/ext/qt/qtitem.cc new/gst-plugins-good-1.26.3/ext/qt/qtitem.cc --- old/gst-plugins-good-1.26.2/ext/qt/qtitem.cc 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/ext/qt/qtitem.cc 2025-06-26 22:25:24.000000000 +0200 @@ -207,6 +207,16 @@ return this->priv->force_aspect_ratio; } +void +QtGLVideoItem::setAcceptEvents(bool accept) +{ + if (accept == acceptEvents) + return; + + acceptEvents = accept; + Q_EMIT acceptEventsChanged(acceptEvents); +} + bool QtGLVideoItem::itemInitialized() { @@ -495,18 +505,21 @@ g_object_unref (element); } g_mutex_unlock (&this->priv->lock); + event->setAccepted(acceptEvents); } void -QtGLVideoItem::hoverEnterEvent(QHoverEvent *) +QtGLVideoItem::hoverEnterEvent(QHoverEvent *event) { mouseHovering = true; + event->setAccepted(acceptEvents); } void -QtGLVideoItem::hoverLeaveEvent(QHoverEvent *) +QtGLVideoItem::hoverLeaveEvent(QHoverEvent *event) { mouseHovering = false; + event->setAccepted(acceptEvents); } void @@ -535,6 +548,7 @@ } } g_mutex_unlock (&this->priv->lock); + event->setAccepted(acceptEvents); } void @@ -597,6 +611,7 @@ g_object_unref (element); g_mutex_unlock (&this->priv->lock); + event->setAccepted(acceptEvents); } void @@ -649,12 +664,14 @@ { forceActiveFocus(); sendMouseEvent(event, TRUE); + event->setAccepted(acceptEvents); } void QtGLVideoItem::mouseReleaseEvent(QMouseEvent * event) { sendMouseEvent(event, FALSE); + event->setAccepted(acceptEvents); } void diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/ext/qt/qtitem.h new/gst-plugins-good-1.26.3/ext/qt/qtitem.h --- old/gst-plugins-good-1.26.2/ext/qt/qtitem.h 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/ext/qt/qtitem.h 2025-06-26 22:25:24.000000000 +0200 @@ -71,6 +71,10 @@ READ getForceAspectRatio WRITE setForceAspectRatio NOTIFY forceAspectRatioChanged) + Q_PROPERTY(bool acceptEvents + READ getAcceptEvents + WRITE setAcceptEvents + NOTIFY acceptEventsChanged) public: QtGLVideoItem(); @@ -82,6 +86,9 @@ bool getForceAspectRatio(); bool itemInitialized(); + bool getAcceptEvents() const { return acceptEvents; } + void setAcceptEvents(bool accept); + QSharedPointer<QtGLVideoItemInterface> getInterface() { return proxy; }; /* private for C interface ... */ QtGLVideoItemPrivate *priv; @@ -89,6 +96,7 @@ Q_SIGNALS: void itemInitializedChanged(); void forceAspectRatioChanged(bool); + void acceptEventsChanged(bool acceptEvents); private Q_SLOTS: void handleWindowChanged(QQuickWindow * win); @@ -117,6 +125,7 @@ quint32 mousePressedButton; bool mouseHovering; + bool acceptEvents = true; QSharedPointer<QtGLVideoItemInterface> proxy; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/ext/qt6/qt6glitem.cc new/gst-plugins-good-1.26.3/ext/qt6/qt6glitem.cc --- old/gst-plugins-good-1.26.2/ext/qt6/qt6glitem.cc 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/ext/qt6/qt6glitem.cc 2025-06-26 22:25:24.000000000 +0200 @@ -193,6 +193,16 @@ emit forceAspectRatioChanged(force_aspect_ratio); } +void +Qt6GLVideoItem::setAcceptEvents(bool accept) +{ + if (accept == acceptEvents) + return; + + acceptEvents = accept; + Q_EMIT acceptEventsChanged(acceptEvents); +} + bool Qt6GLVideoItem::getForceAspectRatio() { @@ -487,18 +497,22 @@ g_object_unref (element); } g_mutex_unlock (&this->priv->lock); + + event->setAccepted(acceptEvents); } void -Qt6GLVideoItem::hoverEnterEvent(QHoverEvent *) +Qt6GLVideoItem::hoverEnterEvent(QHoverEvent *event) { mouseHovering = true; + event->setAccepted(acceptEvents); } void -Qt6GLVideoItem::hoverLeaveEvent(QHoverEvent *) +Qt6GLVideoItem::hoverLeaveEvent(QHoverEvent *event) { mouseHovering = false; + event->setAccepted(acceptEvents); } void @@ -527,6 +541,7 @@ } } g_mutex_unlock (&this->priv->lock); + event->setAccepted(acceptEvents); } void @@ -589,6 +604,7 @@ g_object_unref (element); g_mutex_unlock (&this->priv->lock); + event->setAccepted(acceptEvents); } void @@ -641,12 +657,14 @@ { forceActiveFocus(); sendMouseEvent(event, TRUE); + event->setAccepted(acceptEvents); } void Qt6GLVideoItem::mouseReleaseEvent(QMouseEvent * event) { sendMouseEvent(event, FALSE); + event->setAccepted(acceptEvents); } void diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/ext/qt6/qt6glitem.h new/gst-plugins-good-1.26.3/ext/qt6/qt6glitem.h --- old/gst-plugins-good-1.26.2/ext/qt6/qt6glitem.h 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/ext/qt6/qt6glitem.h 2025-06-26 22:25:24.000000000 +0200 @@ -73,7 +73,10 @@ READ getForceAspectRatio WRITE setForceAspectRatio NOTIFY forceAspectRatioChanged) - + Q_PROPERTY(bool acceptEvents + READ getAcceptEvents + WRITE setAcceptEvents + NOTIFY acceptEventsChanged) public: Qt6GLVideoItem(); ~Qt6GLVideoItem(); @@ -83,6 +86,8 @@ void setForceAspectRatio(bool); bool getForceAspectRatio(); bool itemInitialized(); + bool getAcceptEvents() const { return acceptEvents; } + void setAcceptEvents(bool accept); QSharedPointer<Qt6GLVideoItemInterface> getInterface() { return proxy; }; /* private for C interface ... */ @@ -91,6 +96,7 @@ Q_SIGNALS: void itemInitializedChanged(); void forceAspectRatioChanged(bool); + void acceptEventsChanged(bool acceptEvents); private Q_SLOTS: void handleWindowChanged(QQuickWindow * win); @@ -120,6 +126,7 @@ quint32 mousePressedButton; bool mouseHovering; + bool acceptEvents = true; QSharedPointer<Qt6GLVideoItemInterface> proxy; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst/audioparsers/gstaacparse.c new/gst-plugins-good-1.26.3/gst/audioparsers/gstaacparse.c --- old/gst-plugins-good-1.26.2/gst/audioparsers/gstaacparse.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst/audioparsers/gstaacparse.c 2025-06-26 22:25:24.000000000 +0200 @@ -555,6 +555,12 @@ guint8 num_side_channel_elements; guint8 num_back_channel_elements; guint8 num_lfe_channel_elements; + guint8 program_config_skipping_data; + guint8 mixdown_present_skipflag; + guint8 is_cpe; + guint8 total_num_channel_elements; + guint8 total_num_channel; + guint8 channel_element_tag; if (!gst_bit_reader_get_bits_uint8 (br, &element_instance_tag, 4)) return FALSE; @@ -568,13 +574,55 @@ return FALSE; if (!gst_bit_reader_get_bits_uint8 (br, &num_back_channel_elements, 4)) return FALSE; - if (!gst_bit_reader_get_bits_uint8 (br, &num_lfe_channel_elements, 4)) + if (!gst_bit_reader_get_bits_uint8 (br, &num_lfe_channel_elements, 2)) return FALSE; - GST_LOG_OBJECT (aacparse, "channels front %d side %d back %d lfe %d ", - num_front_channel_elements, num_side_channel_elements, - num_back_channel_elements, num_lfe_channel_elements); - *channels = num_front_channel_elements + num_side_channel_elements + - num_back_channel_elements + num_lfe_channel_elements; + + // skip num_assoc_data_elements + num_valid_cc_elements + if (!gst_bit_reader_get_bits_uint8 (br, &program_config_skipping_data, 7)) + return FALSE; + + if (!gst_bit_reader_get_bits_uint8 (br, &mixdown_present_skipflag, 1)) + return FALSE; + + // skip mono_mixdown_element_number + if (mixdown_present_skipflag) + if (!gst_bit_reader_get_bits_uint8 (br, &program_config_skipping_data, 4)) + return FALSE; + + if (!gst_bit_reader_get_bits_uint8 (br, &mixdown_present_skipflag, 1)) + return FALSE; + + // skip stereo_mixdown_element_number + if (mixdown_present_skipflag) + if (!gst_bit_reader_get_bits_uint8 (br, &program_config_skipping_data, 4)) + return FALSE; + + if (!gst_bit_reader_get_bits_uint8 (br, &mixdown_present_skipflag, 1)) + return FALSE; + + // skip matrix_mixdown_idx + pseudo_surround_enable + if (mixdown_present_skipflag) { + if (!gst_bit_reader_get_bits_uint8 (br, &program_config_skipping_data, 3)) + return FALSE; + } + + total_num_channel_elements = + num_front_channel_elements + num_side_channel_elements + + num_back_channel_elements; + + total_num_channel = total_num_channel_elements + num_lfe_channel_elements; + // If cpe (coupled), then each single channel element represents two channels + for (guint8 i = 0; i < total_num_channel_elements; i++) { + if (!gst_bit_reader_get_bits_uint8 (br, &is_cpe, 1)) + return FALSE; + if (is_cpe) + total_num_channel += 1; + if (!gst_bit_reader_get_bits_uint8 (br, &channel_element_tag, 4)) + return FALSE; + } + + *channels = total_num_channel; + GST_LOG_OBJECT (aacparse, "total channels : %d", *channels); return TRUE; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst/imagefreeze/gstimagefreeze.c new/gst-plugins-good-1.26.3/gst/imagefreeze/gstimagefreeze.c --- old/gst-plugins-good-1.26.2/gst/imagefreeze/gstimagefreeze.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst/imagefreeze/gstimagefreeze.c 2025-06-26 22:25:24.000000000 +0200 @@ -85,6 +85,8 @@ GstEvent * event); static gboolean gst_image_freeze_src_query (GstPad * pad, GstObject * parent, GstQuery * query); +static gboolean gst_image_freeze_src_activate_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); static GstStaticPadTemplate sink_pad_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -178,6 +180,8 @@ GST_DEBUG_FUNCPTR (gst_image_freeze_src_event)); gst_pad_set_query_function (self->srcpad, GST_DEBUG_FUNCPTR (gst_image_freeze_src_query)); + gst_pad_set_activatemode_function (self->srcpad, + GST_DEBUG_FUNCPTR (gst_image_freeze_src_activate_mode)); gst_pad_use_fixed_caps (self->srcpad); gst_element_add_pad (GST_ELEMENT (self), self->srcpad); @@ -609,6 +613,45 @@ return ret; } +static gboolean +gst_image_freeze_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean res; + GstImageFreeze *self = GST_IMAGE_FREEZE (parent); + + switch (mode) { + case GST_PAD_MODE_PUSH: + if (!active) { + GST_DEBUG_OBJECT (pad, "Pad deactivating"); + + g_mutex_lock (&self->lock); + self->flushing = TRUE; + if (self->clock_id) { + GST_DEBUG_OBJECT (self, "unlock clock wait"); + gst_clock_id_unschedule (self->clock_id); + } + g_cond_signal (&self->blocked_cond); + g_mutex_unlock (&self->lock); + + res = gst_pad_stop_task (pad); + gst_image_freeze_reset (self); + } else { + GST_DEBUG_OBJECT (pad, "Pad activating"); + gst_image_freeze_reset (self); + + g_mutex_lock (&self->lock); + self->flushing = FALSE; + g_mutex_unlock (&self->lock); + res = TRUE; + } + break; + default: + res = FALSE; + break; + } + return res; +} static gboolean gst_image_freeze_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) @@ -866,6 +909,14 @@ GstFlowReturn flow_ret; g_mutex_lock (&self->lock); + + if (self->flushing) { + GST_DEBUG_OBJECT (pad, "Flushing"); + gst_buffer_unref (buffer); + g_mutex_unlock (&self->lock); + return GST_FLOW_FLUSHING; + } + if (self->buffer && !self->allow_replace) { GST_DEBUG_OBJECT (pad, "Already have a buffer, dropping"); gst_buffer_unref (buffer); @@ -1192,9 +1243,7 @@ switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: - gst_image_freeze_reset (self); g_mutex_lock (&self->lock); - self->flushing = FALSE; self->blocked = TRUE; g_mutex_unlock (&self->lock); if (self->is_live) @@ -1208,16 +1257,9 @@ break; case GST_STATE_CHANGE_PAUSED_TO_READY: g_mutex_lock (&self->lock); - self->flushing = TRUE; - if (self->clock_id) { - GST_DEBUG_OBJECT (self, "unlock clock wait"); - gst_clock_id_unschedule (self->clock_id); - } self->blocked = FALSE; g_cond_signal (&self->blocked_cond); g_mutex_unlock (&self->lock); - gst_image_freeze_reset (self); - gst_pad_stop_task (self->srcpad); break; default: break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst/isomp4/atoms.c new/gst-plugins-good-1.26.3/gst/isomp4/atoms.c --- old/gst-plugins-good-1.26.2/gst/isomp4/atoms.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst/isomp4/atoms.c 2025-06-26 22:25:24.000000000 +0200 @@ -3475,6 +3475,67 @@ moov->chunks_offset = offset; } +guint64 +atom_moov_calc_stco_to_co64_conversion_total_offset (AtomMOOV * moov, + guint64 offset) +{ + /* Whenever any stco32 chunk offset exceeds its 32-bit limit, the + * corresponding stco32 atom must be converted to a stco64 atom, increasing + * its size. Because faststart files place the moov atom before the mdat + * atom, this conversion must increase the value of the chunk offsets in all + * stco32 and stco64 atoms, so they continue to point to the correct + * positions within the mdat atom. Increasing the chunk offsets in a single + * stco32 atom may require its conversion to stco64. This in turn increases + * the chunk offsets of other atoms, some of which may also need to be + * converted, potentially requiring further conversions. + * + * This function takes as input an offset representing the size from the + * start of the moov atom to the start of the mdat data. It uses this offset + * to determine whether any stco32 atom would require conversion to stco64, + * incrementing the offset accordingly. The function returns this total + * offset that should be applied to adjust the chunk offsets in all + * stco32 and stco64 atoms. It does not perform any atom conversions nor + * update any chunk offsets itself, as this is done by subsequent calls to + * atom_moov_chunks_set_offset() and atom_moov_copy_data() (in that order). + */ + + GList *stco32_atoms = NULL; + for (GList * l = moov->traks; l; l = l->next) { + AtomTRAK *trak = (AtomTRAK *) l->data; + AtomSTCO64 *stco64 = (AtomSTCO64 *) & trak->mdia.minf.stbl.stco64; + if (stco64->header.header.type == FOURCC_stco) { + stco32_atoms = g_list_prepend (stco32_atoms, stco64); + } + } + + GList *pending_stco32_atoms = stco32_atoms; + while (pending_stco32_atoms) { + AtomSTCO64 *stco64 = (AtomSTCO64 *) pending_stco32_atoms->data; + + if ((stco64->max_offset + offset) > G_MAXUINT32) { + /* This stco32 atom must be converted to stco64 to be able to accommodate + * its new maximum offset, which exceeds the representable range of a + * 32-bit entry and therefore requires a 64-bit one. Neither this + * conversion nor the update of the atom's maximum chunk offset is + * performed by this function. + * However, the value of the total offset must be increased to account + * for the larger size of a stco64 atom, as each one of its chunk offset + * entries will be increased from 4 bytes to 8 bytes. */ + offset += atom_array_get_len (&stco64->entries) * 4; + /* This atom must be treated as it were already converted to stco64. All + * stco32 atoms must be re-evaluated considering the updated offset. */ + stco32_atoms = g_list_remove (stco32_atoms, stco64); + pending_stco32_atoms = stco32_atoms; + } else { + pending_stco32_atoms = g_list_next (pending_stco32_atoms); + } + } + + g_list_free (stco32_atoms); + + return offset; +} + void atom_trak_update_bitrates (AtomTRAK * trak, guint32 avg_bitrate, guint32 max_bitrate) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst/isomp4/atoms.h new/gst-plugins-good-1.26.3/gst/isomp4/atoms.h --- old/gst-plugins-good-1.26.2/gst/isomp4/atoms.h 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst/isomp4/atoms.h 2025-06-26 22:25:24.000000000 +0200 @@ -967,6 +967,7 @@ void atom_moov_chunks_set_offset (AtomMOOV *moov, guint32 offset); void atom_moov_add_trak (AtomMOOV *moov, AtomTRAK *trak); guint atom_moov_get_trak_count (AtomMOOV *moov); +guint64 atom_moov_calc_stco_to_co64_conversion_total_offset (AtomMOOV *moov, guint64 offset); guint atom_framerate_to_timescale (gint fps_n, gint fps_d); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst/isomp4/gstqtmux.c new/gst-plugins-good-1.26.3/gst/isomp4/gstqtmux.c --- old/gst-plugins-good-1.26.2/gst/isomp4/gstqtmux.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst/isomp4/gstqtmux.c 2025-06-26 22:25:24.000000000 +0200 @@ -4198,9 +4198,18 @@ ret = gst_qt_mux_send_extra_atoms (qtmux, FALSE, &offset, FALSE); if (ret != GST_FLOW_OK) return ret; + + offset = + atom_moov_calc_stco_to_co64_conversion_total_offset (qtmux->moov, + offset); break; } default: + /* The file is not being written as faststart, so the offset, which + * corresponds to the file size up to the start of the mdat payload, does + * not include the size of the moov atom, as this comes after the mdat + * atom. Therefore, any changes to the moov atom will not affect the + * offset value assigned here */ offset = qtmux->header_size; break; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst/multifile/gstsplitmuxsink.c new/gst-plugins-good-1.26.3/gst/multifile/gstsplitmuxsink.c --- old/gst-plugins-good-1.26.2/gst/multifile/gstsplitmuxsink.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst/multifile/gstsplitmuxsink.c 2025-06-26 22:25:24.000000000 +0200 @@ -184,6 +184,7 @@ static GQuark PAD_CONTEXT; static GQuark EOS_FROM_US; static GQuark SINK_FRAGMENT_INFO; +static GQuark SENT_FRAGMENT_CLOSED; /* EOS_FROM_US is only valid in async-finalize mode. We need to know whether * to forward an incoming EOS message, but we cannot rely on the state of the * splitmux anymore, so we set this qdata on the sink instead. @@ -207,6 +208,8 @@ EOS_FROM_US = g_quark_from_static_string ("splitmuxsink-eos-from-us"); SINK_FRAGMENT_INFO = g_quark_from_static_string ("splitmuxsink-fragment-info"); + SENT_FRAGMENT_CLOSED = + g_quark_from_static_string ("splitmuxsink-sent-fragment-closed"); GST_DEBUG_CATEGORY_INIT (splitmux_debug, "splitmuxsink", 0, "Split File Muxing Sink"); } @@ -2322,6 +2325,7 @@ g_list_foreach (splitmux->contexts, (GFunc) restart_context, splitmux); update_output_fragment_info (splitmux); + g_object_set_qdata ((GObject *) sink, SENT_FRAGMENT_CLOSED, NULL); send_fragment_opened_closed_msg (splitmux, TRUE, sink); /* FIXME: Is this always the correct next state? */ @@ -2376,7 +2380,11 @@ sink = GST_ELEMENT (GST_MESSAGE_SRC (message)); GST_SPLITMUX_LOCK (splitmux); - send_fragment_opened_closed_msg (splitmux, FALSE, sink); + if (!g_object_get_qdata ((GObject *) sink, SENT_FRAGMENT_CLOSED)) { + send_fragment_opened_closed_msg (splitmux, FALSE, sink); + g_object_set_qdata ((GObject *) sink, SENT_FRAGMENT_CLOSED, + GINT_TO_POINTER (TRUE)); + } if (splitmux->async_finalize) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst/rtp/gstrtph265depay.c new/gst-plugins-good-1.26.3/gst/rtp/gstrtph265depay.c --- old/gst-plugins-good-1.26.2/gst/rtp/gstrtph265depay.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst/rtp/gstrtph265depay.c 2025-06-26 22:25:24.000000000 +0200 @@ -503,6 +503,7 @@ GstBitReader br; guint32 tmp; guint8 tmp8 = 0; + gsize src_offset, dst_offset; guint32 max_sub_layers_minus1, temporal_id_nesting_flag, chroma_format_idc, bit_depth_luma_minus8, bit_depth_chroma_minus8, min_spatial_segmentation_idc; @@ -544,7 +545,42 @@ max_sub_layers_minus1 = ((nalmap.data[2]) >> 1) & 0x07; temporal_id_nesting_flag = nalmap.data[2] & 0x01; - gst_bit_reader_init (&br, nalmap.data + 15, nalmap.size - 15); + /* HEVCDecoderConfigurationVersion = 1 */ + data[0] = 1; + + /* Copy from profile_tier_level (Rec. ITU-T H.265 (04/2013) section 7.3.3 + * + * profile_space | tier_flat | profile_idc | + * profile_compatibility_flags | constraint_indicator_flags | + * level_idc | progressive_source_flag | interlaced_source_flag + * non_packed_constraint_flag | frame_only_constraint_flag + * reserved_zero_44bits | level_idc */ + + guint n_zero_bytes = 0; + // 16 bit nal header and sps-vps id. + for (src_offset = 3, dst_offset = 1; dst_offset < 13; src_offset++) { + if (src_offset >= nalmap.size) + // SPS not long enough + return FALSE; + + if (n_zero_bytes == 2 && nalmap.data[src_offset] == 0x03) { + n_zero_bytes = 0; + // ignore emulation prevention bytes: [0x00, 0x00, 0x03] + continue; + } + + if (nalmap.data[src_offset] == 0x00) + n_zero_bytes++; + else + n_zero_bytes = 0; + + data[dst_offset] = nalmap.data[src_offset]; + dst_offset++; + } + + // FIXME: does not parse any sub layers + gst_bit_reader_init (&br, nalmap.data + src_offset, + nalmap.size - src_offset); gst_rtp_read_golomb (&br, &tmp); /* sps_seq_parameter_set_id */ gst_rtp_read_golomb (&br, &chroma_format_idc); /* chroma_format_idc */ @@ -570,23 +606,6 @@ "Ignoring min_spatial_segmentation for now (assuming zero)"); min_spatial_segmentation_idc = 0; /* NOTE - we ignore this for now, but in a perfect world, we should continue parsing to obtain the real value */ - - gst_buffer_unmap (g_ptr_array_index (rtph265depay->sps, 0), &nalmap); - - /* HEVCDecoderConfigurationVersion = 1 */ - data[0] = 1; - - /* Copy from profile_tier_level (Rec. ITU-T H.265 (04/2013) section 7.3.3 - * - * profile_space | tier_flat | profile_idc | - * profile_compatibility_flags | constraint_indicator_flags | - * level_idc | progressive_source_flag | interlaced_source_flag - * non_packed_constraint_flag | frame_only_constraint_flag - * reserved_zero_44bits | level_idc */ - gst_buffer_map (g_ptr_array_index (rtph265depay->sps, 0), &nalmap, - GST_MAP_READ); - for (i = 0; i < 12; i++) - data[i + 1] = nalmap.data[i]; gst_buffer_unmap (g_ptr_array_index (rtph265depay->sps, 0), &nalmap); /* min_spatial_segmentation_idc */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst/rtp/gstrtph265pay.c new/gst-plugins-good-1.26.3/gst/rtp/gstrtph265pay.c --- old/gst-plugins-good-1.26.2/gst/rtp/gstrtph265pay.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst/rtp/gstrtph265pay.c 2025-06-26 22:25:24.000000000 +0200 @@ -1094,7 +1094,8 @@ } } else if (rtph265pay->vps_sps_pps_interval == -1 && (nal_type == GST_H265_NAL_SLICE_IDR_W_RADL - || nal_type == GST_H265_NAL_SLICE_IDR_N_LP)) { + || nal_type == GST_H265_NAL_SLICE_IDR_N_LP + || nal_type == GST_H265_NAL_SLICE_CRA_NUT)) { /* send VPS/SPS/PPS before every IDR frame */ send_ps = TRUE; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst/rtpmanager/rtptwcc.c new/gst-plugins-good-1.26.3/gst/rtpmanager/rtptwcc.c --- old/gst-plugins-good-1.26.2/gst/rtpmanager/rtptwcc.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst/rtpmanager/rtptwcc.c 2025-06-26 22:25:24.000000000 +0200 @@ -105,7 +105,7 @@ GstClockTime feedback_interval; guint64 remote_ts_base; - gint64 base_time_prev; + guint32 base_time_prev; }; G_DEFINE_TYPE (RTPTWCCManager, rtp_twcc_manager, G_TYPE_OBJECT); @@ -128,7 +128,9 @@ twcc->feedback_interval = GST_CLOCK_TIME_NONE; twcc->next_feedback_send_time = GST_CLOCK_TIME_NONE; - twcc->remote_ts_base = -1; + /* Start with an initial offset of 1 << 24 so that we don't risk going below 0 + if a future timestamp is earlier than the first. */ + twcc->remote_ts_base = G_GINT64_CONSTANT (1) << 24; } static void @@ -1019,8 +1021,8 @@ GArray *twcc_packets; guint16 base_seqnum; guint16 packet_count; - GstClockTime base_time; - gint64 base_time_ext; + guint32 base_time; + gint64 base_time_diff; GstClockTime ts_rounded; guint8 fb_pkt_count; guint packets_parsed = 0; @@ -1036,10 +1038,6 @@ base_seqnum = GST_READ_UINT16_BE (&fci_data[0]); packet_count = GST_READ_UINT16_BE (&fci_data[2]); base_time = GST_READ_UINT24_BE (&fci_data[4]); - /* Sign-extend the base_time from a 24-bit integer into a 64-bit signed integer - * so that we can calculate diffs with regular 64-bit operations. */ - base_time_ext = - (base_time & 0x800000) ? base_time | 0xFFFFFFFFFF800000 : base_time; fb_pkt_count = fci_data[7]; GST_DEBUG ("Parsed TWCC feedback: base_seqnum: #%u, packet_count: %u, " @@ -1075,17 +1073,16 @@ if (twcc->sent_packets->len > 0) first_sent_pkt = &g_array_index (twcc->sent_packets, SentPacket, 0); - if (twcc->remote_ts_base == -1) { - /* Add an initial offset of 1 << 24 so that we don't risk going below 0 if - * a future extended timestamp is earlier than the first. */ - twcc->remote_ts_base = (G_GINT64_CONSTANT (1) << 24) + base_time_ext; - } else { - /* Calculate our internal accumulated reference timestamp by continously - * adding the diff between the current and the previous sign-extended - * reference time. */ - twcc->remote_ts_base += base_time_ext - twcc->base_time_prev; - } - twcc->base_time_prev = base_time_ext; + base_time_diff = (gint64) ((base_time - twcc->base_time_prev) & 0xFFFFFF); + if (base_time_diff >= 0x7FFFFF) { + base_time_diff -= 0x1000000; + } + twcc->base_time_prev = base_time; + + /* Calculate our internal accumulated reference timestamp by continously + adding the diff between the current and the previous reference time. */ + twcc->remote_ts_base += base_time_diff; + /* Our internal accumulated reference time is in units of 64ms, propagate as * GstClockTime in ns. */ ts_rounded = twcc->remote_ts_base * REF_TIME_UNIT; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst/rtsp/gstrtspsrc.c new/gst-plugins-good-1.26.3/gst/rtsp/gstrtspsrc.c --- old/gst-plugins-good-1.26.2/gst/rtsp/gstrtspsrc.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst/rtsp/gstrtspsrc.c 2025-06-26 22:25:24.000000000 +0200 @@ -7246,6 +7246,9 @@ send_error: { + if (src->busy_cmd == CMD_CLOSE && res == GST_RTSP_EEOF) + return res; + gchar *str = gst_rtsp_strresult (res); if (res != GST_RTSP_EINTR) { @@ -9279,6 +9282,9 @@ } send_error: { + if (res == GST_RTSP_EEOF) + goto close; + gchar *str = gst_rtsp_strresult (res); gst_rtsp_message_unset (&request); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst/wavparse/gstwavparse.c new/gst-plugins-good-1.26.3/gst/wavparse/gstwavparse.c --- old/gst-plugins-good-1.26.2/gst/wavparse/gstwavparse.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst/wavparse/gstwavparse.c 2025-06-26 22:25:24.000000000 +0200 @@ -1482,7 +1482,6 @@ buf = NULL; res = gst_wavparse_pull_range_exact (wav, wav->offset + 8, size, &buf); - goto header_pull_error; if (res == GST_FLOW_EOS) break; else if (res != GST_FLOW_OK) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/gst-plugins-good.doap new/gst-plugins-good-1.26.3/gst-plugins-good.doap --- old/gst-plugins-good-1.26.2/gst-plugins-good.doap 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/gst-plugins-good.doap 2025-06-26 22:25:24.000000000 +0200 @@ -34,6 +34,16 @@ <release> <Version> + <revision>1.26.3</revision> + <branch>1.26</branch> + <name></name> + <created>2025-06-26</created> + <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-plugins-good/gst-plugins-good-1.26.3.tar.xz" /> + </Version> + </release> + + <release> + <Version> <revision>1.26.2</revision> <branch>1.26</branch> <name></name> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/meson.build new/gst-plugins-good-1.26.3/meson.build --- old/gst-plugins-good-1.26.2/meson.build 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/meson.build 2025-06-26 22:25:24.000000000 +0200 @@ -1,5 +1,5 @@ project('gst-plugins-good', 'c', - version : '1.26.2', + version : '1.26.3', meson_version : '>= 1.4', default_options : [ 'warning_level=1', 'buildtype=debugoptimized' ]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/sys/osxvideo/osxvideosink.m new/gst-plugins-good-1.26.3/sys/osxvideo/osxvideosink.m --- old/gst-plugins-good-1.26.2/sys/osxvideo/osxvideosink.m 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/sys/osxvideo/osxvideosink.m 2025-06-26 22:25:24.000000000 +0200 @@ -454,7 +454,6 @@ GstStructure * structure) { GstOSXVideoSink *osxvideosink = GST_OSX_VIDEO_SINK (navigation); - GstPad *peer; GstEvent *event; GstVideoRectangle src = { 0, }; GstVideoRectangle dst = { 0, }; @@ -462,9 +461,7 @@ NSRect bounds; gdouble x, y, xscale = 1.0, yscale = 1.0; - peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (osxvideosink)); - - if (!peer || !osxvideosink->osxwindow) + if (!osxvideosink->osxwindow) return; event = gst_event_new_navigation (structure); @@ -508,8 +505,14 @@ (gdouble) y * yscale, NULL); } - gst_pad_send_event (peer, event); - gst_object_unref (peer); + gst_event_ref (event); + if (!gst_pad_push_event (GST_VIDEO_SINK_PAD (osxvideosink), event)) { + /* If the event was not handled/used upstream, + * we post it as a message on the bus so that applications can handle it */ + gst_element_post_message (GST_ELEMENT_CAST (osxvideosink), + gst_navigation_message_new_event (GST_OBJECT_CAST (osxvideosink), event)); + } + gst_event_unref (event); } static void diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/sys/v4l2/gstv4l2object.c new/gst-plugins-good-1.26.3/sys/v4l2/gstv4l2object.c --- old/gst-plugins-good-1.26.2/sys/v4l2/gstv4l2object.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/sys/v4l2/gstv4l2object.c 2025-06-26 22:25:24.000000000 +0200 @@ -2596,19 +2596,66 @@ else colorspace = fmt.fmt.pix.colorspace; - if (colorspace == req_cspace) { - if (gst_v4l2_object_get_colorspace (v4l2object, &fmt, &cinfo)) - gst_v4l2_object_fill_colorimetry_list (&list, &cinfo); - if (colorspace == V4L2_COLORSPACE_REC709) { - /* support for full-range variants of colorspaces V4L2_COLORSPACE_REC709 - * (such as Apple's full-range bt709 variant 1:3:5:1) */ - struct v4l2_format alt_fmt; - memcpy (&alt_fmt, &fmt, sizeof (alt_fmt)); - - if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) - alt_fmt.fmt.pix_mp.quantization = V4L2_QUANTIZATION_FULL_RANGE; - else - alt_fmt.fmt.pix.quantization = V4L2_QUANTIZATION_FULL_RANGE; + if (colorspace != req_cspace) + continue; + + if (gst_v4l2_object_get_colorspace (v4l2object, &fmt, &cinfo)) + gst_v4l2_object_fill_colorimetry_list (&list, &cinfo); + + if (colorspace == V4L2_COLORSPACE_REC709 || + colorspace == V4L2_COLORSPACE_470_SYSTEM_BG) { + /* support for full-range variants of colorspaces V4L2_COLORSPACE_REC709 + * (such as Apple's full-range bt709 variant 1:3:5:1) and colorspace + * V4L2_COLORSPACE_470_SYSTEM_BG */ + struct v4l2_format alt_fmt; + enum v4l2_quantization quantization; + memcpy (&alt_fmt, &fmt, sizeof (alt_fmt)); + + if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) + alt_fmt.fmt.pix_mp.quantization = V4L2_QUANTIZATION_FULL_RANGE; + else + alt_fmt.fmt.pix.quantization = V4L2_QUANTIZATION_FULL_RANGE; + + if (gst_v4l2_object_try_fmt (v4l2object, &alt_fmt) == 0) { + if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) { + colorspace = alt_fmt.fmt.pix_mp.colorspace; + quantization = alt_fmt.fmt.pix_mp.quantization; + } else { + colorspace = alt_fmt.fmt.pix.colorspace; + quantization = alt_fmt.fmt.pix.quantization; + } + + if (colorspace != req_cspace + || quantization != V4L2_QUANTIZATION_FULL_RANGE) + continue; + + if (gst_v4l2_object_get_colorspace (v4l2object, &alt_fmt, &cinfo)) + gst_v4l2_object_fill_colorimetry_list (&list, &cinfo); + } + } + if (colorspace == V4L2_COLORSPACE_BT2020) { + /* support for colorimetry bt2100-pq, variant of colorspace + * V4L2_COLORSPACE_BT2020 */ + struct v4l2_format alt_fmt; + enum v4l2_xfer_func xfer_func; + memcpy (&alt_fmt, &fmt, sizeof (alt_fmt)); + + if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) + alt_fmt.fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_SMPTE2084; + else + alt_fmt.fmt.pix.xfer_func = V4L2_XFER_FUNC_SMPTE2084; + + if (gst_v4l2_object_try_fmt (v4l2object, &alt_fmt) == 0) { + if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) { + colorspace = alt_fmt.fmt.pix_mp.colorspace; + xfer_func = alt_fmt.fmt.pix_mp.xfer_func; + } else { + colorspace = alt_fmt.fmt.pix.colorspace; + xfer_func = alt_fmt.fmt.pix.xfer_func; + } + + if (colorspace != req_cspace || xfer_func != V4L2_XFER_FUNC_SMPTE2084) + continue; if (gst_v4l2_object_get_colorspace (v4l2object, &alt_fmt, &cinfo)) gst_v4l2_object_fill_colorimetry_list (&list, &cinfo); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/sys/v4l2/gstv4l2transform.c new/gst-plugins-good-1.26.3/sys/v4l2/gstv4l2transform.c --- old/gst-plugins-good-1.26.2/sys/v4l2/gstv4l2transform.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/sys/v4l2/gstv4l2transform.c 2025-06-26 22:25:24.000000000 +0200 @@ -932,6 +932,7 @@ self->v4l2output->mode == GST_V4L2_IO_DMABUF_IMPORT) { if (!gst_v4l2_object_try_import (self->v4l2output, inbuf)) { GST_ERROR_OBJECT (self, "cannot import buffers from upstream"); + gst_object_unref (pool); return GST_FLOW_ERROR; } @@ -961,8 +962,7 @@ goto beach; do { - if (pool) - g_object_unref (pool); + g_object_unref (pool); pool = gst_base_transform_get_buffer_pool (trans); if (!gst_buffer_pool_set_active (pool, TRUE)) @@ -995,8 +995,7 @@ } beach: - if (pool) - g_object_unref (pool); + g_object_unref (pool); return ret; activate_failed: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/sys/v4l2/gstv4l2videoenc.c new/gst-plugins-good-1.26.3/sys/v4l2/gstv4l2videoenc.c --- old/gst-plugins-good-1.26.2/sys/v4l2/gstv4l2videoenc.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/sys/v4l2/gstv4l2videoenc.c 2025-06-26 22:25:24.000000000 +0200 @@ -660,8 +660,7 @@ ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL); if (ret != GST_FLOW_OK) { - if (cpool) - gst_object_unref (cpool); + gst_object_unref (cpool); goto beach; } @@ -669,8 +668,7 @@ GST_LOG_OBJECT (encoder, "Process output buffer"); ret = gst_v4l2_buffer_pool_process (cpool, &buffer, NULL); - if (cpool) - gst_object_unref (cpool); + gst_object_unref (cpool); if (ret != GST_FLOW_OK) goto beach; @@ -789,26 +787,23 @@ self->input_state->caps, self->v4l2output->info.vinfo.size, min, min)) { gst_structure_free (config); - if (opool) - gst_object_unref (opool); + gst_object_unref (opool); goto activate_failed; } if (!gst_buffer_pool_set_config (opool, config)) { - if (opool) - gst_object_unref (opool); + gst_object_unref (opool); goto activate_failed; } } if (!gst_buffer_pool_set_active (opool, TRUE)) { - if (opool) - gst_object_unref (opool); + gst_object_unref (opool); goto activate_failed; } } - if (opool) - gst_object_unref (opool); + + gst_object_unref (opool); } if (task_state == GST_TASK_STOPPED || task_state == GST_TASK_PAUSED) { @@ -816,8 +811,7 @@ GstBufferPool *cpool = gst_v4l2_object_get_buffer_pool (self->v4l2capture); active = gst_buffer_pool_set_active (cpool, TRUE); - if (cpool) - gst_object_unref (cpool); + gst_object_unref (cpool); } if (!active) { GST_WARNING_OBJECT (self, "Could not activate capture buffer pool."); @@ -854,8 +848,7 @@ GstBufferPool *opool = gst_v4l2_object_get_buffer_pool (self->v4l2output); ret = gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (opool), &frame->input_buffer, &frame->system_frame_number); - if (opool) - gst_object_unref (opool); + gst_object_unref (opool); } GST_VIDEO_ENCODER_STREAM_LOCK (encoder); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/tests/check/elements/aacparse.c new/gst-plugins-good-1.26.3/tests/check/elements/aacparse.c --- old/gst-plugins-good-1.26.2/tests/check/elements/aacparse.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/tests/check/elements/aacparse.c 2025-06-26 22:25:24.000000000 +0200 @@ -28,6 +28,7 @@ #include "parser.h" #define SRC_CAPS_CDATA "audio/mpeg, mpegversion=(int)4, framed=(boolean)false, codec_data=(buffer)1190" +#define SRC_CAPS_CDATA_6CH "audio/mpeg, mpegversion=(int)4, framed=(boolean)false, codec_data=(buffer)118004c841000108800d4c61766336312e31392e31303156e500," #define SRC_CAPS_TMPL "audio/mpeg, framed=(boolean)false, mpegversion=(int){2,4}" #define SRC_CAPS_RAW "audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, rate=(int)48000, channels=(int)2, codec_data=(buffer)1190" @@ -289,6 +290,35 @@ GST_END_TEST; +GST_START_TEST (test_parse_handle_codec_data_6ch) +{ + GstCaps *caps; + GstStructure *s; + const gchar *stream_format; + + /* Push random data. It should get through since the parser should be + * initialized because it got codec_data in the caps */ + caps = gst_parser_test_get_output_caps (NULL, 100, SRC_CAPS_CDATA_6CH); + fail_unless (caps != NULL); + + /* Check that the negotiated caps are as expected */ + /* When codec_data is present, parser assumes that data is version 4 */ + GST_LOG ("aac output caps: %" GST_PTR_FORMAT, caps); + s = gst_caps_get_structure (caps, 0); + fail_unless (gst_structure_has_name (s, "audio/mpeg")); + fail_unless_structure_field_int_equals (s, "mpegversion", 4); + fail_unless_structure_field_int_equals (s, "channels", 6); + fail_unless_structure_field_int_equals (s, "rate", 48000); + fail_unless (gst_structure_has_field (s, "codec_data")); + fail_unless (gst_structure_has_field (s, "stream-format")); + stream_format = gst_structure_get_string (s, "stream-format"); + fail_unless (strcmp (stream_format, "raw") == 0); + + gst_caps_unref (caps); +} + +GST_END_TEST; + GST_START_TEST (test_parse_proxy_constraints) { GstCaps *caps, *resultcaps; @@ -369,6 +399,7 @@ /* Other tests */ tcase_add_test (tc_chain, test_parse_handle_codec_data); + tcase_add_test (tc_chain, test_parse_handle_codec_data_6ch); /* caps tests */ tcase_add_test (tc_chain, test_parse_proxy_constraints); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gst-plugins-good-1.26.2/tests/check/elements/rtpsession.c new/gst-plugins-good-1.26.3/tests/check/elements/rtpsession.c --- old/gst-plugins-good-1.26.2/tests/check/elements/rtpsession.c 2025-05-30 00:56:43.000000000 +0200 +++ new/gst-plugins-good-1.26.3/tests/check/elements/rtpsession.c 2025-06-26 22:25:24.000000000 +0200 @@ -4387,6 +4387,211 @@ GST_END_TEST; +GST_START_TEST (test_twcc_reference_time_wrap) +{ + SessionHarness *h = session_harness_new (); + guint i, j; + GstBuffer *buf; + GstEvent *event; + GValueArray *packets_array; + + /* This fci packet is used as a template for generating fci packets in the + * test. In these packets only the reference time is patched, which means we + * get a completely unrealistic sequence of packets all claiming to report the + * status of packets with sequence number 1 and 2. This is fine in this test + * since we're only concerned with changes to the reference timestamp and want + * to get rid of other noise. */ + guint8 fci[] = { + 0x00, 0x01, /* base sequence number: 1 */ + 0x00, 0x02, /* packet status count: 2 */ + 0xcc, 0xcc, 0xcc, /* reference time (will be replaced in each packet sent) */ + 0x00, /* feedback packet count: 0 */ + 0x40, 0x02, /* run-length with large delta for 2 packets: 0 1 0 0 0 0 0 0 | 0 0 0 0 0 0 1 0 */ + /* recv deltas: */ + 0x0f, 0xa0, /* large delta: +0:00:01.000000000 */ + 0xe0, 0xc0, /* large delta: -0:00:02.000000000 */ + /* padding */ + 0x00, 0x00 + }; + + guint8 fci_base_times[][3] = { + {0x7f, 0xff, 0xfe}, /* 0x7ffffe <=> +149:07:50.784 */ + /* increase over signed wrap */ + {0x80, 0x00, 0x03}, /* 0x800003 <=> +149:07:51.104 */ + /* decrease over signed wrap */ + {0x7f, 0xff, 0xf7}, /* 0x7ffff7 <=> +149:07:50.336 */ + /* increase over signed wrap again */ + {0xff, 0xff, 0xf1}, /* 0xfffff1 <=> +298:15:40.864 */ + /* increase over unsigned wrap */ + {0x00, 0x00, 0x05}, /* 0x000005 (+0x1000000) <=> +298:15:42.144 */ + /* decrease over unsigned wrap */ + {0xff, 0xff, 0xfe}, /* 0xfffffe <=> +298:15:41.696 */ + /* increase over unsigned wrap again */ + {0x55, 0x55, 0x55}, /* 0x555555 (+0x1000000) <=> +397:40:55.744 */ + /* increase over signed wrap again */ + {0xaa, 0xaa, 0xaa}, /* 0xaaaaaa (+0x1000000) <=> +497:06:09.664 */ + /* increase over unsigned wrap again */ + {0x00, 0x00, 0x42}, /* 0x000042 (+0x1000000) <=> +597:31:27.872 */ + }; + + GstClockTime exp_ts[] = { + TWCC_REF_TIME_INITIAL_OFFSET + 0x07ffffeLL * 64 * GST_MSECOND + + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x07ffffeLL * 64 * GST_MSECOND - + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x0800003LL * 64 * GST_MSECOND + + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x0800003LL * 64 * GST_MSECOND - + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x07ffff7LL * 64 * GST_MSECOND + + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x07ffff7LL * 64 * GST_MSECOND - + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x0fffff1LL * 64 * GST_MSECOND + + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x0fffff1LL * 64 * GST_MSECOND - + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x1000005LL * 64 * GST_MSECOND + + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x1000005LL * 64 * GST_MSECOND - + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x0fffffeLL * 64 * GST_MSECOND + + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x0fffffeLL * 64 * GST_MSECOND - + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x1555555LL * 64 * GST_MSECOND + + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x1555555LL * 64 * GST_MSECOND - + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x1aaaaaaLL * 64 * GST_MSECOND + + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x1aaaaaaLL * 64 * GST_MSECOND - + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x2000042LL * 64 * GST_MSECOND + + 1 * GST_SECOND, + TWCC_REF_TIME_INITIAL_OFFSET + 0x2000042LL * 64 * GST_MSECOND - + 1 * GST_SECOND, + }; + + for (i = 0; i < sizeof (fci_base_times) / 3; ++i) { + /* patch our fci packet with a new reference time */ + fci[4] = fci_base_times[i][0]; + fci[5] = fci_base_times[i][1]; + fci[6] = fci_base_times[i][2]; + buf = generate_twcc_feedback_rtcp (fci, sizeof (fci)); + session_harness_recv_rtcp (h, buf); + } + + for (i = 0; i < 2; i++) + gst_event_unref (gst_harness_pull_upstream_event (h->send_rtp_h)); + + for (i = 0; i < sizeof (fci_base_times) / 3; ++i) { + event = gst_harness_pull_upstream_event (h->send_rtp_h); + packets_array = + g_value_get_boxed (gst_structure_get_value (gst_event_get_structure + (event), "packets")); + + fail_unless_equals_int (packets_array->n_values, 2); + + /* iterate all values in the array and check that the remote-ts property is set to 0 */ + for (j = 0; j < packets_array->n_values; j++) { + const GstStructure *pkt_s = + gst_value_get_structure (g_value_array_get_nth (packets_array, j)); + GstClockTime ts = 1; /* initialize to non-zero */ + fail_unless (gst_structure_get_clock_time (pkt_s, "remote-ts", &ts)); + fail_unless_equals_clocktime (ts, exp_ts[i * 2 + j]); + } + + gst_event_unref (event); + } + + session_harness_free (h); +} + +GST_END_TEST; + +GST_START_TEST (test_twcc_reference_time_wrap_start_negative) +{ + SessionHarness *h = session_harness_new (); + guint i, j; + GstBuffer *buf; + GstEvent *event; + GValueArray *packets_array; + + /* This fci packet is used as a template for generating fci packets in the + * test. In these packets only the reference time is patched, which means we + * get a completely unrealistic sequence of packets all claiming to report the + * status of packets with sequence number 1 and 2. This is fine in this test + * since we're only concerned with changes to the reference timestamp and want + * to get rid of other noise. */ + guint8 fci[] = { + 0x00, 0x01, /* base sequence number: 1 */ + 0x00, 0x02, /* packet status count: 2 */ + 0xcc, 0xcc, 0xcc, /* reference time (will be replaced in each packet sent) */ + 0x00, /* feedback packet count: 0 */ + 0x40, 0x02, /* run-length with large delta for 2 packets: 0 1 0 0 0 0 0 0 | 0 0 0 0 0 0 1 0 */ + /* recv deltas: */ + 0x0f, 0xa0, /* large delta: +0:00:01.000000000 */ + 0xe0, 0xc0, /* large delta: -0:00:02.000000000 */ + /* padding */ + 0x00, 0x00 + }; + + guint8 fci_base_times[][3] = { + {0x80, 0x00, 0x03}, /* 0x800003 <=> +149:07:51.104 */ + /* decrease over signed wrap */ + {0x7f, 0xff, 0xf7}, /* 0x7ffff7 <=> +149:07:50.336 */ + /* increase over signed wrap again */ + {0xff, 0xff, 0xf1}, /* 0xfffff1 <=> +298:15:40.864 */ + }; + + /* note that we should not add TWCC_REF_TIME_INITIAL_OFFSET here because we + * subtract from that */ + GstClockTime exp_ts[] = { + 0x800003LL * 64 * GST_MSECOND + 1 * GST_SECOND, + 0x800003LL * 64 * GST_MSECOND - 1 * GST_SECOND, + 0x7ffff7LL * 64 * GST_MSECOND + 1 * GST_SECOND, + 0x7ffff7LL * 64 * GST_MSECOND - 1 * GST_SECOND, + 0xfffff1LL * 64 * GST_MSECOND + 1 * GST_SECOND, + 0xfffff1LL * 64 * GST_MSECOND - 1 * GST_SECOND, + }; + + for (i = 0; i < sizeof (fci_base_times) / 3; ++i) { + /* patch our fci packet with a new reference time */ + fci[4] = fci_base_times[i][0]; + fci[5] = fci_base_times[i][1]; + fci[6] = fci_base_times[i][2]; + buf = generate_twcc_feedback_rtcp (fci, sizeof (fci)); + session_harness_recv_rtcp (h, buf); + } + + for (i = 0; i < 2; i++) + gst_event_unref (gst_harness_pull_upstream_event (h->send_rtp_h)); + + for (i = 0; i < sizeof (fci_base_times) / 3; ++i) { + event = gst_harness_pull_upstream_event (h->send_rtp_h); + packets_array = + g_value_get_boxed (gst_structure_get_value (gst_event_get_structure + (event), "packets")); + + fail_unless_equals_int (packets_array->n_values, 2); + + /* iterate all values in the array and check that the remote-ts property is set to 0 */ + for (j = 0; j < packets_array->n_values; j++) { + const GstStructure *pkt_s = + gst_value_get_structure (g_value_array_get_nth (packets_array, j)); + GstClockTime ts = 1; /* initialize to non-zero */ + fail_unless (gst_structure_get_clock_time (pkt_s, "remote-ts", &ts)); + fail_unless_equals_clocktime (ts, exp_ts[i * 2 + j]); + } + + gst_event_unref (event); + } + + session_harness_free (h); +} + +GST_END_TEST; static Suite * rtpsession_suite (void) @@ -4467,6 +4672,8 @@ G_N_ELEMENTS (test_twcc_feedback_interval_ctx)); tcase_add_test (tc_chain, test_twcc_feedback_count_wrap); tcase_add_test (tc_chain, test_twcc_feedback_old_seqnum); + tcase_add_test (tc_chain, test_twcc_reference_time_wrap); + tcase_add_test (tc_chain, test_twcc_reference_time_wrap_start_negative); return s; } ++++++ gst-plugins-good.obsinfo ++++++ --- /var/tmp/diff_new_pack.hMJPNa/_old 2025-07-03 12:12:01.757602245 +0200 +++ /var/tmp/diff_new_pack.hMJPNa/_new 2025-07-03 12:12:01.761602410 +0200 @@ -1,5 +1,5 @@ name: gst-plugins-good -version: 1.26.2 -mtime: 1748559403 -commit: 100c21e1faf68efe7f3830b6e9f856760697ab48 +version: 1.26.3 +mtime: 1750969524 +commit: 87bc0c6e949e3dcc440658f78ef52aa8088cb62f