reactor-runtime 2.3.1__tar.gz → 2.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/PKG-INFO +1 -1
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/pyproject.toml +1 -1
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/model/reactor_model.py +30 -3
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/pipeline/reactor_pipeline.py +17 -4
- reactor_runtime-2.3.2/src/reactor_runtime/transports/gstreamer/probes/__init__.py +5 -0
- reactor_runtime-2.3.2/src/reactor_runtime/transports/gstreamer/probes/fps_probe.py +119 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime.egg-info/PKG-INFO +1 -1
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime.egg-info/SOURCES.txt +2 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/README.md +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/setup.cfg +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/api/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_cli/commands/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_cli/commands/init.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_cli/commands/run.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_cli/commands/schema.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_cli/main.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_cli/utils/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_cli/utils/config.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_cli/utils/runtime.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_cli/utils/version.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/config.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/defaults.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/driver/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/driver/pipeline_executor.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/driver/step_result.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/events/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/events/connected.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/events/event.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/events/messages.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/events/upload.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/internal/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/internal/input_buffer.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/internal/output_buffer.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/internal/reactor_core.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/model/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/model/decorators.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/model/handlers.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/pipeline/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/pipeline/idle.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/pipeline/input_state.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/tracks/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/tracks/descriptors.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/tracks/input.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/tracks/output.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/upload.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/model_state.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/backends/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/backends/base.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/backends/file.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/backends/otlp.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/helpers.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/plotting/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/plotting/plot_profiling.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/profiler.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/singleton.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/runtime_api.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/runtimes/headless/config.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/runtimes/headless/headless_runtime.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/runtimes/headless/input_feeder.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/runtimes/http/config.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/runtimes/http/http_runtime.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/runtimes/http/types.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/schema.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/schema_validator.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/aiortc/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/aiortc/audio_track.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/aiortc/client.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/aiortc/frame_conversion.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/aiortc/ice_connection.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/aiortc/video_track.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/config.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/events.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/client.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/decoders/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/decoders/av1.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/decoders/base.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/decoders/factory.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/decoders/h264.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/decoders/h265.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/decoders/vp8.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/decoders/vp9.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/encoders/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/encoders/av1.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/encoders/base.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/encoders/factory.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/encoders/h264.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/encoders/h265.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/encoders/opus.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/encoders/vp8.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/encoders/vp9.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/gst.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/gst_helpers.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/receiver/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/receiver/audio.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/receiver/base.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/receiver/video.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/sdp/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/sdp/bundle.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/sdp/codec.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/sdp/extmap.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/sdp/ice.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/sender/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/sender/audio.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/sender/base.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/sender/video.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/settings.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/signals.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/ice_uris.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/interface.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/media.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/types.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/utils/launch.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/utils/loader.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/utils/log.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/utils/messages.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/utils/typing.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime.egg-info/dependency_links.txt +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime.egg-info/entry_points.txt +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime.egg-info/requires.txt +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime.egg-info/top_level.txt +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/template/README.md +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/template/__init__.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/template/config.yml +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/template/model.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/template/pipeline.py +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/template/reactor.yaml +0 -0
- {reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/template/requirements.txt +0 -0
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/model/reactor_model.py
RENAMED
|
@@ -12,7 +12,8 @@ from __future__ import annotations
|
|
|
12
12
|
|
|
13
13
|
import asyncio
|
|
14
14
|
import dataclasses
|
|
15
|
-
|
|
15
|
+
import os
|
|
16
|
+
from typing import Any, Callable, List, Optional, Tuple, Type
|
|
16
17
|
|
|
17
18
|
from reactor_runtime.interface.events.connected import Connected, Disconnected
|
|
18
19
|
from reactor_runtime.interface.events.event import Event
|
|
@@ -96,12 +97,22 @@ class ReactorModel(ReactorCore):
|
|
|
96
97
|
dispatch_table = build_dispatch_table(handlers)
|
|
97
98
|
|
|
98
99
|
dispatcher = asyncio.create_task(self._dispatcher(handlers, dispatch_table))
|
|
100
|
+
crash: Optional[BaseException] = None
|
|
99
101
|
try:
|
|
100
102
|
await self.run()
|
|
101
103
|
except asyncio.CancelledError:
|
|
102
104
|
logger.info("Model cancelled")
|
|
103
|
-
except Exception:
|
|
104
|
-
|
|
105
|
+
except Exception as exc:
|
|
106
|
+
# Don't swallow-and-return: log, clean up via finally, then
|
|
107
|
+
# fail-fast (REA-1740). ``ReactorPipeline.run()`` contains
|
|
108
|
+
# its own per-session crashes, so this only fires for custom
|
|
109
|
+
# ``run()`` overrides.
|
|
110
|
+
crash = exc
|
|
111
|
+
logger.exception(
|
|
112
|
+
"run() crashed — terminating the process",
|
|
113
|
+
model=type(self).__name__,
|
|
114
|
+
exc_type=type(exc).__name__,
|
|
115
|
+
)
|
|
105
116
|
finally:
|
|
106
117
|
dispatcher.cancel()
|
|
107
118
|
try:
|
|
@@ -109,6 +120,22 @@ class ReactorModel(ReactorCore):
|
|
|
109
120
|
except asyncio.CancelledError:
|
|
110
121
|
pass
|
|
111
122
|
|
|
123
|
+
if crash is not None:
|
|
124
|
+
self._fail_fast(crash)
|
|
125
|
+
|
|
126
|
+
def _fail_fast(self, exc: BaseException) -> None:
|
|
127
|
+
"""Terminate the process after an unrecoverable ``run()`` error.
|
|
128
|
+
|
|
129
|
+
Uses :func:`os._exit` (not ``sys.exit``) so the whole process
|
|
130
|
+
goes away regardless of thread. Override in subclasses or
|
|
131
|
+
tests.
|
|
132
|
+
"""
|
|
133
|
+
logger.critical(
|
|
134
|
+
"Terminating process after unhandled run() exception",
|
|
135
|
+
exc_type=type(exc).__name__,
|
|
136
|
+
)
|
|
137
|
+
os._exit(1)
|
|
138
|
+
|
|
112
139
|
# ------------------------------------------------------------------
|
|
113
140
|
# run() — override with your generation loop
|
|
114
141
|
# ------------------------------------------------------------------
|
|
@@ -241,6 +241,10 @@ class ReactorPipeline(ReactorModel):
|
|
|
241
241
|
except BufferClosed:
|
|
242
242
|
logger.debug("Input buffer closed, ending session")
|
|
243
243
|
break
|
|
244
|
+
# Any other exception propagates up through the outer
|
|
245
|
+
# try/finally (gen close + state reset) and out of
|
|
246
|
+
# ``run()`` — ``_lifecycle`` then fails-fast via
|
|
247
|
+
# ``_fail_fast`` (REA-1740).
|
|
244
248
|
|
|
245
249
|
if output is Idle:
|
|
246
250
|
await asyncio.sleep(0.005)
|
|
@@ -251,10 +255,19 @@ class ReactorPipeline(ReactorModel):
|
|
|
251
255
|
else:
|
|
252
256
|
await self.emit(output)
|
|
253
257
|
finally:
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
+
# Swallow exceptions from ``gen.close()`` only so a buggy
|
|
259
|
+
# ``inference()`` ``finally`` cannot mask the original
|
|
260
|
+
# exception on its way up to ``_lifecycle``.
|
|
261
|
+
try:
|
|
262
|
+
if is_async:
|
|
263
|
+
await gen.aclose()
|
|
264
|
+
else:
|
|
265
|
+
gen.close()
|
|
266
|
+
except Exception:
|
|
267
|
+
logger.exception(
|
|
268
|
+
"generator.close() raised during teardown",
|
|
269
|
+
model=type(self).__name__,
|
|
270
|
+
)
|
|
258
271
|
self.state = None
|
|
259
272
|
for buf in self._input_buffers.values():
|
|
260
273
|
buf.reset()
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Copyright (c) 2026 Reactor Technologies, Inc. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Buffer-count FPS probes on GStreamer pads.
|
|
5
|
+
Each :class:`FpsProbe` instance is independent: attach one probe per pad /
|
|
6
|
+
measurement site (e.g. after ``videoconvert``, after an encoder, on a queue src pad).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import time
|
|
12
|
+
from typing import Any, Optional
|
|
13
|
+
|
|
14
|
+
from reactor_runtime.transports.gstreamer.gst import Gst
|
|
15
|
+
from reactor_runtime.utils.log import get_logger
|
|
16
|
+
|
|
17
|
+
logger = get_logger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class FpsProbe:
|
|
21
|
+
"""
|
|
22
|
+
Install a ``Gst.PadProbeType.BUFFER`` probe that reports buffers per second
|
|
23
|
+
over a rolling wall-clock window (default 1s of monotonic time).
|
|
24
|
+
Instances do not share state. Typical usage::
|
|
25
|
+
probe_videoconvert = FpsProbe("video_after_videoconvert")
|
|
26
|
+
probe_videoconvert.attach(videoconvert.get_static_pad("src"))
|
|
27
|
+
probe_encoder = FpsProbe("video_after_encoder")
|
|
28
|
+
probe_encoder.attach(encoder_element.get_static_pad("src"))
|
|
29
|
+
``last_fps`` is updated at the end of each completed window. Each completed
|
|
30
|
+
window is logged at INFO.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
name: str,
|
|
36
|
+
*,
|
|
37
|
+
window_ns: Optional[int] = None,
|
|
38
|
+
) -> None:
|
|
39
|
+
self._name = name
|
|
40
|
+
self._window_ns = int(Gst.SECOND if window_ns is None else window_ns)
|
|
41
|
+
if self._window_ns <= 0:
|
|
42
|
+
raise ValueError("window_ns must be positive")
|
|
43
|
+
|
|
44
|
+
self._pad: Optional[Gst.Pad] = None
|
|
45
|
+
self._probe_id: Optional[int] = None
|
|
46
|
+
self._window_start_ns: Optional[int] = None
|
|
47
|
+
self._count = 0
|
|
48
|
+
self._last_fps: Optional[float] = None
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def name(self) -> str:
|
|
52
|
+
return self._name
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def last_fps(self) -> Optional[float]:
|
|
56
|
+
"""Buffers per second from the last completed ``window_ns`` interval."""
|
|
57
|
+
return self._last_fps
|
|
58
|
+
|
|
59
|
+
def attach(self, pad: Gst.Pad) -> None:
|
|
60
|
+
"""
|
|
61
|
+
Add this probe on *pad* (usually a src pad, downstream of the element under test).
|
|
62
|
+
Raises:
|
|
63
|
+
RuntimeError: if this instance already has a probe installed.
|
|
64
|
+
"""
|
|
65
|
+
if self._probe_id:
|
|
66
|
+
raise RuntimeError(
|
|
67
|
+
f"FpsProbe({self._name!r}) is already attached; call detach() first"
|
|
68
|
+
)
|
|
69
|
+
self._pad = pad
|
|
70
|
+
self._window_start_ns = None
|
|
71
|
+
self._count = 0
|
|
72
|
+
self._probe_id = pad.add_probe(
|
|
73
|
+
Gst.PadProbeType.BUFFER,
|
|
74
|
+
self._buffer_probe,
|
|
75
|
+
None, # user_data (PyGObject passes this as the 3rd callback arg)
|
|
76
|
+
)
|
|
77
|
+
if not self._probe_id:
|
|
78
|
+
self._pad = None
|
|
79
|
+
raise RuntimeError(f"FpsProbe({self._name!r}): pad.add_probe() failed")
|
|
80
|
+
|
|
81
|
+
def detach(self) -> None:
|
|
82
|
+
"""Remove the probe from the pad, if installed."""
|
|
83
|
+
if self._pad is not None and self._probe_id is not None:
|
|
84
|
+
self._pad.remove_probe(self._probe_id)
|
|
85
|
+
self._pad = None
|
|
86
|
+
self._probe_id = None
|
|
87
|
+
self._window_start_ns = None
|
|
88
|
+
self._count = 0
|
|
89
|
+
self._last_fps = None
|
|
90
|
+
|
|
91
|
+
def _buffer_probe(
|
|
92
|
+
self,
|
|
93
|
+
_pad: Gst.Pad,
|
|
94
|
+
info: Gst.PadProbeInfo,
|
|
95
|
+
_user_data: Any,
|
|
96
|
+
) -> Gst.PadProbeReturn:
|
|
97
|
+
buf = info.get_buffer()
|
|
98
|
+
if buf is None:
|
|
99
|
+
return Gst.PadProbeReturn.OK
|
|
100
|
+
|
|
101
|
+
now = time.monotonic_ns()
|
|
102
|
+
window_start = self._window_start_ns
|
|
103
|
+
if window_start is None:
|
|
104
|
+
self._window_start_ns = now
|
|
105
|
+
return Gst.PadProbeReturn.OK
|
|
106
|
+
|
|
107
|
+
self._count += 1
|
|
108
|
+
elapsed = now - window_start
|
|
109
|
+
if elapsed >= self._window_ns:
|
|
110
|
+
# buffers / second for the window that just ended
|
|
111
|
+
fps = self._count * 1_000_000_000 / elapsed
|
|
112
|
+
self._last_fps = fps
|
|
113
|
+
logger.info(
|
|
114
|
+
f"gstreamer_fps_probe name={self._name} fps={fps:.2f} buffers={self._count} window_s={elapsed / 1e9:.3f}",
|
|
115
|
+
)
|
|
116
|
+
self._window_start_ns = now
|
|
117
|
+
self._count = 0
|
|
118
|
+
|
|
119
|
+
return Gst.PadProbeReturn.OK
|
|
@@ -101,6 +101,8 @@ src/reactor_runtime/transports/gstreamer/encoders/h265.py
|
|
|
101
101
|
src/reactor_runtime/transports/gstreamer/encoders/opus.py
|
|
102
102
|
src/reactor_runtime/transports/gstreamer/encoders/vp8.py
|
|
103
103
|
src/reactor_runtime/transports/gstreamer/encoders/vp9.py
|
|
104
|
+
src/reactor_runtime/transports/gstreamer/probes/__init__.py
|
|
105
|
+
src/reactor_runtime/transports/gstreamer/probes/fps_probe.py
|
|
104
106
|
src/reactor_runtime/transports/gstreamer/receiver/__init__.py
|
|
105
107
|
src/reactor_runtime/transports/gstreamer/receiver/audio.py
|
|
106
108
|
src/reactor_runtime/transports/gstreamer/receiver/base.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/driver/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/driver/step_result.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/events/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/events/connected.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/events/event.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/events/messages.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/events/upload.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/internal/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/model/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/model/decorators.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/model/handlers.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/pipeline/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/pipeline/idle.py
RENAMED
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/tracks/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/tracks/descriptors.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/tracks/input.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/interface/tracks/output.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/backends/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/backends/base.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/backends/file.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/backends/otlp.py
RENAMED
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/profiling/plotting/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/runtimes/headless/config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/runtimes/http/http_runtime.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/aiortc/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/aiortc/audio_track.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/aiortc/client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/aiortc/video_track.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/gst.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/sdp/ice.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/settings.py
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime/transports/gstreamer/signals.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{reactor_runtime-2.3.1 → reactor_runtime-2.3.2}/src/reactor_runtime.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|