player: NV12 zero-copy SDL upload path for Rockchip MPP hardware decode

- _Frame: add pixel_format ('BGRA'|'NV12'), uv_pixels, uv_pitch fields
- _create_appsink: accept NV12 caps when R36S_HW_DECODE=1 (NV12;BGRA fallback)
- render(): choose SDL_PIXELFORMAT_NV12 texture + SDL_UpdateNVTexture for NV12
  frames, avoiding any software colourspace conversion on the CPU
- _on_new_sample: detect format via VideoInfo.finfo.name, extract Y+UV planes
  separately from NV12 GStreamer buffers
- _destroy_texture: reset _texture_format to 'BGRA'
- deploy/arkos/MatHacks.sh: set R36S_HW_DECODE=1 to activate the path
- tests/test_player.py: add finfo mock, pixel_format to SimpleNamespace frame
This commit is contained in:
Matteo Benedetto
2026-03-23 22:58:08 +01:00
parent e23c57318f
commit 6e15fcab5a
3 changed files with 92 additions and 14 deletions
+15 -4
View File
@@ -188,11 +188,17 @@ class FakeGst:
Caps = SimpleNamespace(from_string=lambda value: value)
class _FakeFinfo:
def __init__(self, name):
self.name = name
class FakeVideoInfoValue:
def __init__(self, width, height, stride):
def __init__(self, width, height, stride, fmt="BGRA"):
self.width = width
self.height = height
self.stride = [stride]
self.stride = [stride, stride]
self.finfo = _FakeFinfo(fmt)
class FakeVideoInfo:
@@ -201,7 +207,12 @@ class FakeVideoInfo:
structure = caps.get_structure(0)
width = structure.get_value("width")
height = structure.get_value("height")
return FakeVideoInfoValue(width, height, width * 4)
fmt = "BGRA"
try:
fmt = structure.get_value("format") or fmt
except Exception:
pass
return FakeVideoInfoValue(width, height, width * 4, fmt)
class FakeGstVideo:
@@ -341,7 +352,7 @@ class TestGStreamerBackend:
def test_render_uploads_latest_frame_and_clears_dirty_flag(self, monkeypatch):
backend, _pipeline, _sink = self._make_backend()
backend._latest_frame = SimpleNamespace(width=320, height=180, pitch=1280, pixels=b"\x00" * (320 * 180 * 4))
backend._latest_frame = SimpleNamespace(width=320, height=180, pitch=1280, pixels=b"\x00" * (320 * 180 * 4), pixel_format="BGRA", uv_pixels=None, uv_pitch=0)
backend._frame_dirty = True
calls = []