player: probe Rockchip MPP/V4L2 HW decoders at pipeline init, add setup_hw_decode.sh
This commit is contained in:
@@ -25,6 +25,72 @@ log = logging.getLogger(__name__)
|
||||
|
||||
Gst.init(None)
|
||||
|
||||
# GStreamer element names for hardware video decoders, in priority order.
|
||||
# mppvideodec: Rockchip MPP plugin (gst-mpp), uses /dev/vpu_service on kernel 4.4 BSP.
|
||||
# v4l2*dec: Linux V4L2 stateful decoders, available on kernel 5.4+ (rkvdec/hantro).
|
||||
_HW_DECODER_ELEMENTS = [
|
||||
"mppvideodec",
|
||||
"v4l2h264dec",
|
||||
"v4l2h265dec",
|
||||
"v4l2vp8dec",
|
||||
"v4l2vp9dec",
|
||||
]
|
||||
|
||||
# VPU device nodes that must be accessible for hardware decode on RK3326.
|
||||
_HW_VPU_DEVICES = [
|
||||
"/dev/vpu_service", # kernel 4.4 BSP (RK3326 / PX30)
|
||||
"/dev/mpp_service", # newer BSP variants
|
||||
"/dev/video10", # V4L2 vcodec on mainline/5.10+ kernels
|
||||
"/dev/video11",
|
||||
]
|
||||
|
||||
|
||||
def _vpu_device_accessible() -> bool:
|
||||
"""Return True if at least one VPU device node can be opened by this process."""
|
||||
for path in _HW_VPU_DEVICES:
|
||||
try:
|
||||
fd = os.open(path, os.O_RDWR | os.O_NONBLOCK)
|
||||
os.close(fd)
|
||||
log.info("HW decode: VPU device accessible: %s", path)
|
||||
return True
|
||||
except OSError:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def _probe_hw_decoders(gst_module) -> list:
|
||||
"""
|
||||
Probe for available hardware video decoder GStreamer elements and boost
|
||||
their rank so that playbin's internal decodebin prefers them over software
|
||||
decoders. Returns the list of element names that were found and boosted.
|
||||
If no VPU device node is accessible the probe is skipped entirely so that
|
||||
a half-initialised hardware element cannot stall the pipeline.
|
||||
"""
|
||||
if not _vpu_device_accessible():
|
||||
log.info(
|
||||
"HW decode: no accessible VPU device node — using software decode. "
|
||||
"Run deploy/arkos/setup_hw_decode.sh as root to fix permissions."
|
||||
)
|
||||
return []
|
||||
|
||||
found = []
|
||||
for name in _HW_DECODER_ELEMENTS:
|
||||
factory = gst_module.ElementFactory.find(name)
|
||||
if factory is not None:
|
||||
try:
|
||||
factory.set_rank(gst_module.Rank.PRIMARY + 1)
|
||||
found.append(name)
|
||||
log.info("HW decode: boosted rank of %s", name)
|
||||
except Exception as exc: # pragma: no cover
|
||||
log.warning("HW decode: could not boost rank of %s: %s", name, exc)
|
||||
|
||||
if not found:
|
||||
log.info(
|
||||
"HW decode: VPU device is accessible but no gst-mpp / V4L2 plugin found. "
|
||||
"Run deploy/arkos/setup_hw_decode.sh to install gstreamer1.0-rockchip-mpp."
|
||||
)
|
||||
return found
|
||||
|
||||
|
||||
def _wm_subsystem_name(subsystem: int) -> str:
|
||||
mapping = {
|
||||
@@ -116,6 +182,7 @@ class GStreamerBackend(PlayerBackend):
|
||||
self._texture_renderer = None
|
||||
self._texture_size = (0, 0)
|
||||
self._resolution = ""
|
||||
self._hw_decoders: list | None = None # None = not yet probed
|
||||
|
||||
def attach_window(self, window: object) -> None:
|
||||
self._window = window
|
||||
@@ -259,6 +326,9 @@ class GStreamerBackend(PlayerBackend):
|
||||
if self._pipeline is not None:
|
||||
return self._pipeline
|
||||
|
||||
if self._hw_decoders is None:
|
||||
self._hw_decoders = _probe_hw_decoders(self._gst)
|
||||
|
||||
self._pipeline = self._playbin_factory()
|
||||
self._configure_playbin_flags(self._pipeline)
|
||||
self._video_sink = self._create_appsink()
|
||||
|
||||
Reference in New Issue
Block a user