perf: insert videoscale before appsink to cut NV12 memmove 6.7×

When hardware decode (mppvideodec/NV12) is active, wrap the appsink in a
GstBin with a videoscale element so the VPU decodes at full stream
resolution but Python only receives a frame pre-scaled to the SDL display
size (default 640x480).

Effect:
  NV12 buffer per frame: 3,133,440 B (1080p) → 460,800 B (640x480)
  memmove per frame:     ~33 ms (80.5% budget) → ~5 ms (expected ~12%)

The videoscale bilinear step runs entirely in software on the A35 cores
but scales down 6.7×, so its cost is far lower than the avoided memmove.
SDL still handles final aspect-ratio fitting inside the viewport, so
visual quality is unchanged relative to what the 640x480 display can show.

Fallback: if videoscale is not available, unscaled NV12 is used as before.
This commit is contained in:
Matteo Benedetto
2026-03-24 10:33:33 +01:00
parent eaffa0026d
commit 67224626a5
2 changed files with 81 additions and 8 deletions
+34
View File
@@ -189,6 +189,30 @@ class FakeMessage:
return SimpleNamespace(get_name=lambda: self._structure_name)
class FakeGhostPad:
def __init__(self, name, pad):
self.name = name
def set_active(self, _):
pass
class FakeBin:
def __init__(self, name=""):
self.name = name
self._elements = []
self._pads = []
self.props = {}
def add(self, elem):
self._elements.append(elem)
def add_pad(self, pad):
self._pads.append(pad)
def set_property(self, name, value):
self.props[name] = value
class FakeMapFlags:
READ = 1
@@ -204,6 +228,16 @@ class FakeGst:
SECOND = 1_000_000_000
MSECOND = 1_000_000
Caps = SimpleNamespace(from_string=lambda value: value)
GhostPad = SimpleNamespace(new=lambda name, pad: FakeGhostPad(name, pad))
Bin = SimpleNamespace(new=lambda name="": FakeBin(name))
@staticmethod
def ElementFactory_make(name, alias=None):
return None # signal "not available" so SW fallback kicks in
# GStreamer uses Gst.ElementFactory.make, exposed as class attribute below
ElementFactory = SimpleNamespace(make=lambda name, alias=None: None)
FakeGst.ElementFactory = ElementFactory
class _FakeFinfo: