gstreamer improvements

This commit is contained in:
YS 2022-02-09 14:04:03 +03:00
parent 667cfed077
commit 0911b4fd01
4 changed files with 43 additions and 14 deletions

View File

@ -1,5 +1,4 @@
from __future__ import annotations from __future__ import annotations
from email.policy import default
import json import json
import logging import logging
@ -628,7 +627,7 @@ class CameraConfig(FrigateBaseModel):
else: else:
for input in self.gstreamer.inputs: for input in self.gstreamer.inputs:
gst_cmd = self._get_gstreamer_cmd(self.gstreamer, input) gst_cmd = self._get_gstreamer_cmd(self.gstreamer, input)
logger.error("gstreamer command[%s] %s", self.name, gst_cmd) logger.info("gstreamer command[%s] %s", self.name, gst_cmd)
self._decoder_cmds.append({"roles": input.roles, "cmd": gst_cmd}) self._decoder_cmds.append({"roles": input.roles, "cmd": gst_cmd})
def _get_gstreamer_cmd( def _get_gstreamer_cmd(

View File

@ -17,6 +17,7 @@ VIDEO_CODEC_CAP_NAME = "video codec"
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@lru_cache @lru_cache
def gst_discover( def gst_discover(
source: str, cam_name: str, keys: List[str] source: str, cam_name: str, keys: List[str]
@ -53,12 +54,12 @@ def gst_discover(
), ),
cam_name, cam_name,
) )
return None return {}
except: except:
logger.error( logger.error(
"gst-discoverer-1.0 failed with the message: %s", traceback.format_exc() "gst-discoverer-1.0 failed with the message: %s", traceback.format_exc()
) )
return None return {}
@lru_cache @lru_cache
@ -81,9 +82,7 @@ def gst_inspect_find_codec(codec: Optional[str]) -> List[str]:
for line in data.split("\n") for line in data.split("\n")
if codec is None or codec in line if codec is None or codec in line
] ]
return [ return [item[1].strip() for item in data if len(item) > 1]
item[1].strip() for item in data if len(item) > 1
]
except: except:
logger.error( logger.error(
"gst-inspect-1.0 failed with the message: %s", traceback.format_exc() "gst-inspect-1.0 failed with the message: %s", traceback.format_exc()
@ -228,7 +227,7 @@ class GstreamerBaseBuilder:
self.audio_pipeline is not None and len(self.audio_pipeline) > 0 self.audio_pipeline is not None and len(self.audio_pipeline) > 0
) )
split_mux = f"splitmuxsink async-handling=true " split_mux = f"splitmuxsink async-finalize=true send-keyframe-requests=true max-size-bytes=0 "
if use_audio_pipeline: if use_audio_pipeline:
split_mux = split_mux + "name=mux muxer=mp4mux " split_mux = split_mux + "name=mux muxer=mp4mux "
@ -283,6 +282,14 @@ class GstreamerBaseBuilder:
) )
depay_element = f"rtp{self.video_format}depay" depay_element = f"rtp{self.video_format}depay"
# add rtpjitterbuffer into the input pipeline for reord role if no rtpjitterbuffer has been added already
if use_record:
has_rtpjitterbuffer = "rtpjitterbuffer" in " ".join(self.input_pipeline)
if not has_rtpjitterbuffer:
self.input_pipeline.append(
"rtpjitterbuffer do-lost=true drop-on-latency=true"
)
pipeline = [*self.input_pipeline, depay_element] pipeline = [*self.input_pipeline, depay_element]
# if both detect and record used, split the stream after the depay element # if both detect and record used, split the stream after the depay element
# to avoid encoding for recording # to avoid encoding for recording

View File

@ -22,7 +22,6 @@ from frigate.const import (
CACHE_DIR, CACHE_DIR,
RECORD_DIR, RECORD_DIR,
GSTREAMER_RECORD_SUFFIX, GSTREAMER_RECORD_SUFFIX,
RECORD_SEGMENT_TIME_SECONDS,
) )
from frigate.models import Event, Recordings from frigate.models import Event, Recordings
from frigate.util import area from frigate.util import area
@ -98,7 +97,7 @@ class RecordingMaintainer(threading.Thread):
if camera.endswith(GSTREAMER_RECORD_SUFFIX): if camera.endswith(GSTREAMER_RECORD_SUFFIX):
camera = camera.split(GSTREAMER_RECORD_SUFFIX)[0] camera = camera.split(GSTREAMER_RECORD_SUFFIX)[0]
creation_time = ( creation_time = (
os.path.getmtime(cache_path) - RECORD_SEGMENT_TIME_SECONDS os.path.getctime(cache_path)
) )
start_time = datetime.datetime.utcfromtimestamp(creation_time) start_time = datetime.datetime.utcfromtimestamp(creation_time)
else: else:

View File

@ -284,6 +284,10 @@ class TestGstreamerNvidia(TestCase):
"latency=0", "latency=0",
"do-timestamp=true", "do-timestamp=true",
"!", "!",
"rtpjitterbuffer",
"do-lost=true",
"drop-on-latency=true",
"!",
"rtph264depay", "rtph264depay",
"!", "!",
"tee", "tee",
@ -308,7 +312,9 @@ class TestGstreamerNvidia(TestCase):
"h264parse", "h264parse",
"!", "!",
"splitmuxsink", "splitmuxsink",
"async-handling=true", "async-finalize=true",
"send-keyframe-requests=true",
"max-size-bytes=0",
"location=/tmp/cache/cam_name-gstsplitmuxchunk-%05d.mp4", "location=/tmp/cache/cam_name-gstsplitmuxchunk-%05d.mp4",
"max-size-time=10000000000", "max-size-time=10000000000",
] ]
@ -332,6 +338,10 @@ class TestGstreamerNvidia(TestCase):
"latency=0", "latency=0",
"do-timestamp=true", "do-timestamp=true",
"!", "!",
"rtpjitterbuffer",
"do-lost=true",
"drop-on-latency=true",
"!",
"rtph264depay", "rtph264depay",
"!", "!",
"queue", "queue",
@ -339,7 +349,9 @@ class TestGstreamerNvidia(TestCase):
"h264parse", "h264parse",
"!", "!",
"splitmuxsink", "splitmuxsink",
"async-handling=true", "async-finalize=true",
"send-keyframe-requests=true",
"max-size-bytes=0",
"location=/tmp/cache/cam_name-gstsplitmuxchunk-%05d.mp4", "location=/tmp/cache/cam_name-gstsplitmuxchunk-%05d.mp4",
"max-size-time=10000000000", "max-size-time=10000000000",
] ]
@ -367,6 +379,10 @@ class TestGstreamerNvidia(TestCase):
"latency=0", "latency=0",
"do-timestamp=true", "do-timestamp=true",
"!", "!",
"rtpjitterbuffer",
"do-lost=true",
"drop-on-latency=true",
"!",
"rtph265depay", "rtph265depay",
"!", "!",
"tee", "tee",
@ -391,7 +407,9 @@ class TestGstreamerNvidia(TestCase):
"h265parse", "h265parse",
"!", "!",
"splitmuxsink", "splitmuxsink",
"async-handling=true", "async-finalize=true",
"send-keyframe-requests=true",
"max-size-bytes=0",
"name=mux", "name=mux",
"muxer=mp4mux", "muxer=mp4mux",
"location=/tmp/cache/cam_name-gstsplitmuxchunk-%05d.mp4", "location=/tmp/cache/cam_name-gstsplitmuxchunk-%05d.mp4",
@ -432,6 +450,10 @@ class TestGstreamerNvidia(TestCase):
"latency=0", "latency=0",
"do-timestamp=true", "do-timestamp=true",
"!", "!",
"rtpjitterbuffer",
"do-lost=true",
"drop-on-latency=true",
"!",
"rtph264depay", "rtph264depay",
"!", "!",
"queue", "queue",
@ -439,7 +461,9 @@ class TestGstreamerNvidia(TestCase):
"h264parse", "h264parse",
"!", "!",
"splitmuxsink", "splitmuxsink",
"async-handling=true", "async-finalize=true",
"send-keyframe-requests=true",
"max-size-bytes=0",
"name=mux", "name=mux",
"muxer=mp4mux", "muxer=mp4mux",
"location=/tmp/cache/cam_name-gstsplitmuxchunk-%05d.mp4", "location=/tmp/cache/cam_name-gstsplitmuxchunk-%05d.mp4",