import time
import gi, glob
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GLib
from app.factories import OverlayFactory
import os
os.environ['GST_DEBUG'] = '3'
class GstRunner:
def __init__(self):
self.vehicle_overlay = OverlayFactory.create()
self.pipeline = None
self.last_frame_time = 0
self.pad_udp = None
self.pad_test = None
self.selector = None
def build_pipeline(self):
self.pipeline = Gst.parse_launch(
# === Shared processing ===
"input-selector name=selector ! "
"videoconvert ! "
"cairooverlay name=overlay ! "
"videoconvert ! "
"kmssink "
# === UDP H264 input ===
"udpsrc port=5600 caps=application/x-rtp,media=video,encoding-name=H264,payload=96 ! "
"rtpjitterbuffer latency=100 mode=1 max-misorder-time=300 max-dropout-time=200 max-rtcp-rtp-time-diff=150 ! "
"queue max-size-buffers=5 max-size-bytes=0 max-size-time=0 ! "
"rtph264depay ! "
"h264parse ! "
"avdec_h264 qos=false ! "
"tee name=udpsrc_tee "
"udpsrc_tee. ! queue ! selector.sink_0 "
"udpsrc_tee. ! queue ! fakesink name=probesink sync=false "
# === GL-accelerated Test source ===
"videotestsrc pattern=ball is-live=true ! "
"videorate ! "
"video/x-raw,width=1280,height=720,framerate=30/1 ! "
"queue max-size-buffers=3 leaky=downstream ! "
"videoconvert ! "
# "glupload ! glcolorconvert ! "
# "queue ! "
# "glcolorconvert ! gldownload ! "
"selector.sink_1"
)
# output command
# gst-launch-1.0 -v videotestsrc is-live=true pattern=ball ! video/x-raw,width=1280,height=720,framerate=30/1 ! videoconvert ! x264enc tune=zerolatency bitrate=1000 speed-preset=ultrafast key-int-max=30 ! rtph264pay config-interval=1 pt=96 mtu=1200 ! udpsink host=192.168.1.8 port=5600
self.selector = self.pipeline.get_by_name("selector")
probesink = self.pipeline.get_by_name("probesink")
overlay = self.pipeline.get_by_name("overlay")
# Get input-selector sink pads
self.pad_udp = self.selector.get_static_pad("sink_0")
self.pad_test = self.selector.get_static_pad("sink_1")
# Start with testsrc
self.selector.set_property("active-pad", self.pad_test)
# Watch for decoded frames
def on_probe(pad, info):
self.last_frame_time = GLib.get_monotonic_time()
return Gst.PadProbeReturn.OK
probesink.get_static_pad("sink").add_probe(Gst.PadProbeType.BUFFER, on_probe)
# Overlay drawing
def on_draw_callback(overlay, context, timestamp, duration):
current_overlay = OverlayFactory.get_current()
if current_overlay:
current_overlay.on_draw(overlay, context, timestamp, duration)
overlay.connect("draw", on_draw_callback)
# Check video activity and switch source
def check_video():
now = GLib.get_monotonic_time()
age_sec = (now - self.last_frame_time) / 1_000_000
current = self.selector.get_property("active-pad")
if age_sec < 2:
if current != self.pad_udp:
print("Switching to udpsrc")
self.selector.set_property("active-pad", self.pad_udp)
else:
if current != self.pad_test:
print("Switching to testsrc")
self.selector.set_property("active-pad", self.pad_test)
return True
GLib.timeout_add_seconds(1, check_video)
def start(self):
self.build_pipeline()
if not self.pipeline:
raise RuntimeError("Pipeline build failed")
result = self.pipeline.set_state(Gst.State.PLAYING)
if result == Gst.StateChangeReturn.FAILURE:
raise RuntimeError("Failed to set pipeline to PLAYING")
def stop(self):
if self.pipeline:
def force_shutdown():
self.pipeline.set_state(Gst.State.NULL)
GLib.timeout_add_seconds(1, force_shutdown)
def detect_error_problem(self):
bus = self.pipeline.get_bus()
msg = bus.timed_pop_filtered(
Gst.SECOND,
Gst.MessageType.ERROR | Gst.MessageType.EOS
)
if msg:
if msg.type == Gst.MessageType.ERROR:
err, debug = msg.parse_error()
error_msg = f"Failed to start pipeline. Reason: {err.message} -> {debug.split(":")[-1]}"
if "Could not get allowed GstCaps of device" == err.message:
raise RuntimeError(f"{error_msg} -> {self._detect_monitor_vs_driver_issue()}")
else:
raise RuntimeError(error_msg)
def _detect_monitor_vs_driver_issue(self):
statuses = []
for path in glob.glob("/sys/class/drm/*/status"):
try:
with open(path) as f:
statuses.append(f.read().strip())
except:
pass
if "connected" in statuses:
return "driver issue"
elif "disconnected" in statuses:
return "monitor missing"
return "unknown"
< /code>
Итак, у меня есть две трубы (1 -е ожидает для входного сигнала на порте 5600, 2 -й просто имеет живой тестовый шаблон) < /p>
Когда вход получает сигнал, он работает нормально. И даже когда мы теряем сигнал, программа переключается на «Резервный трубопровод» и отлично воспроизводит шаблон тестирования. < /P>
Проблема в том, что когда у нас нет изображения из 5600 порта, тестовый шаблон просто замораживает только один кадр, воспроизводимый (так что, Каир не может обновляться). До? Нет результата < /li>
< /ul>
У меня нет ошибок. Просто замороженное изображение
Подробнее здесь: https://stackoverflow.com/questions/797 ... nder-issue
Проблема Gstreamer+Cairo с двумя трубопроводами. ⇐ Python
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Ищу уважаемую кодовую базу ImGui и Cairo для функций редактирования текста.
Anonymous » » в форуме C++ - 0 Ответы
- 13 Просмотры
-
Последнее сообщение Anonymous
-