Skip to content

Reimplement gvastreammux by using PTS to cross-stream batch#872

Open
qianlongding wants to merge 10 commits into
mainfrom
gvastreammux-enhance
Open

Reimplement gvastreammux by using PTS to cross-stream batch#872
qianlongding wants to merge 10 commits into
mainfrom
gvastreammux-enhance

Conversation

@qianlongding

@qianlongding qianlongding commented May 28, 2026

Copy link
Copy Markdown
Contributor

Description

Replaces GstCollectPads with per-pad queues + a dedicated output task that assembles batches around a PTS anchor: pick the earliest PTS across non-EOS pads, then collect buffers whose PTS lies within pts-tolerance of that anchor, waiting at most max-wait-time for late pads. Pads that miss the window do not block the batch — a partial batch is pushed and the loop moves on.
Adds a sync-mode property to normalize per-pad PTS before scheduling: none (default, raw PTS), first-pts (each pad starts at 0), segment (GST_EVENT_SEGMENT.start subtraction), pipeline (overwrite with pipeline running time), ntp (use GstReferenceTimestampMeta).

Fixes # (issue)

Any Newly Introduced Dependencies

Please describe any newly introduced 3rd party dependencies in this change. List their name, license information and how they are used in the project.

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

Checklist:

  • I agree to use the MIT license for my code changes.
  • I have not introduced any 3rd party components incompatible with MIT.
  • I have not included any company confidential information, trade secret, password or security token.
  • I have performed a self-review of my code.

- Replace GstCollectPads with per-pad queue + dedicated output task,
  using a PTS anchor + tolerance window to assemble batches and a
  condition variable for back-pressure when queues fill up.
- Coalesce per-pad FLUSH_START / FLUSH_STOP events via a flushing
  pad counter so the downstream flush, task pause, queue reset and
  task restart each happen exactly once per flush cycle.
- Reject pad indices >= 256 in both mux and demux to bound the
  per-pad array size and prevent OOM from arbitrary user-supplied
  sink_N / src_N names; warn on sparse indices at PAUSED.
- Drop the strict src/sink pad count match check in demux since
  pad indices may be sparse.
Different sources can produce buffers whose PTS are on entirely different
timelines (file vs RTSP, multiple cameras with independent clocks, sources
that started at different wall-clock moments). Without normalization, the
batch-anchor + tolerance scheduler either deadlocks (a far-future pad
never enters the window and back-pressures upstream) or oscillates
(anchor jumps between pads each round, producing single-stream batches).

Introduce a 'sync-mode' enum property with five modes:
- none      raw PTS, default (preserves existing behavior)
- first-pts subtract each pad's first observed PTS so all pads start at 0
- segment   subtract each pad's GST_EVENT_SEGMENT.start
- pipeline  overwrite PTS with pipeline running time at arrival, useful
            when at least one source is live and source PTS are unreliable
- ntp       use GstReferenceTimestampMeta as PTS, for absolute cross-device
            time alignment with rtspsrc ntp-sync=true add-reference-
            timestamp-meta=true

Per-pad normalization state (first_pts, segment_start) is reset on
FLUSH_STOP and on PAUSED->READY so seek and pipeline restart establish
fresh baselines. The chain function applies normalization before taking
the mux lock to avoid lengthening the critical section.
The element pages and the multi-stream sample were still describing the
original GstCollectPads + round-robin design with GstGvaStreammuxMeta and
a single max-fps property. Both elements have since been rewritten to use
PTS-anchor batch assembly with per-pad queues, GstAnalyticsBatchMeta for
source tracking, and a configurable sync-mode for cross-pad PTS
normalization.

Update the element pages, the elements index, and the sample (README and
shell script) to reflect:

- the PTS-anchor / max-wait-time / max-queue-size scheduling and
  back-pressure behavior
- the five sync-mode options (none, first-pts, segment, pipeline, ntp)
  with use cases and a NTP/PTP example pipeline
- GstAnalyticsBatchMeta replacing GstGvaStreammuxMeta as the routing
  metadata between mux and demux
- updated property tables, error conditions and tuning notes
- a --sync-mode flag on the sample script with corresponding examples
Pure formatting cleanup of property descriptions, log lines and a stray
blank line. No behavior change.
The struct member was initialized in _init and cleared in _finalize but
never locked or passed to GStreamer. The output task is started via the
4-argument gst_pad_start_task(), which uses an internal lock; only
gst_pad_start_task_full() would have consumed an external GRecMutex.

Remove the field and its init/clear calls.
# Conflicts:
#	samples/gstreamer/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant