mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-02 01:05:20 +03:00
gstreamer improvements
This commit is contained in:
parent
667cfed077
commit
0911b4fd01
@ -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(
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user