Bastelprojekt: Jetson Nano als Deinterlacer von 576i Streams für die Shield

  • Die Shield hat ja bekanntermaßen ein ziemlich nettes AI-Upscaling, was aber leider kein interlaced-Material verarbeiten kann. Hier fällt sie einfach in "Optimiert" zurück und das sieht, zumindest für mich, einfach nur nach "Matsche" aus. Mir ist natürlich bewusst, dass meine 576i Magenta-Streams von den Privaten nun auch nicht gerade wirklich gute Qualität haben, aber historisch betrachtet weiß ich, dass ein gutes Deinterlacing halt doch noch so einiges retten kann.

    Mittlerweile ist der Jetson Nano (4GB) da und läuft. Die Streams werden von diesem bereits über TVHeadend (via ffmpeg-pipe, da TVHeadend leider nur rudimentär RTSP unterstützt) angefragt. Dafür läuft auf dem Nano ein RTSP-Simple-Server der onDemand die Streams via GStreamer-Pipeline bereitstellt. Vorgeschaltet ist noch ein abgespecktes "Dumpstream", da GStreamer leider mit den MagentaTV Streams so nicht direkt arbeiten kann.

    Funktionert rein technisch betrachtet super, lediglich die Umschaltzeiten verlängern sich unweigerlich deutlich - was für mich am Ende aber OK wäre.

    Beim reinen Deinterlacing wird es wohl nicht bleiben was der Nano so leisten muss. Das schafft er ganz locker, wie auch das h264 de- und encoding mit insgesamt ca. 10% CPU insgesamt und bei ~40°C. Es ist nur leider so, dass selbst mit dem besten Deinterlacing die Auflösung sehr gering ist. Die Unschärfe die beim "optimierten" Skalieren der Shield entsteht ist vermutlich tatsächlich so gewollt um die sichtbaren Pixel loszuwerden...

    Trotzdem bin ich zuversichtlich, dass das noch deutlich besser geht und optimiere fröhlich ;)

  • Ist ein wenig schade, das die Jetson platform das nvidia video SDK nicht unterstützt. Ich habe damit und staxrip als Frontend echt gute Ergebnisse beim Deinterlace und reencode von 1080i Daten erreicht. Vorallem sauschnell.

  • @JensK Mal schauen wie weit ich komme ;) Ich optimiere erstmal den Status-Quo, dann schau ich mal in Richtung der Machine-Learning Möglichkeiten, erstmal in Sachen Deinterlacing, dann evtl. noch Skalierung.

    Lustiger Nebenfind auf jeden Fall:
    Vorher lief bei mir Comskip auf nem RPI 3B mit so ca. 20 FPS auf seinen 4 Cores. Der Jetson Nano schafft so in etwa 120 FPS, auf einem Core. Was vorher also ca. 60 Minuten gedauert hat dauert jetzt nur noch maximal 10...

  • So, ich denke meine persönliche Basis steht und bildet den Benchmark für weitere Optimierungen. Der Nano macht im Moment das Beste gstreamer-eigene deinterlacing was möglich ist. Danach mache ich ein ganz leichtes hqdn3d denoising. Im Anschluss wird die vertikale Auflösung des streams um 10% erhöht und wieder runtergerechnet um Fehler des deinterlacings wegzubekommen. Dann wird noch ein leichtes xsharpen drüber gelegt. Die letzteren beiden sind entrans Filter.

    Das Ergebnis ist aus ca 3,5m Distanz echt gut bei 65". Bei 1m sieht man aber natürlich ganz deutlich die geradezu lächerliche Grundauflösung.

    Auf jeden Fall ist das schonmal weit entfernt von der Pixelmatsche die die shield da sonst draus macht.

  • @Canis Nova Soll ich mal einen GitHub Gist fertig machen mit den ganzen Scripten für den Nano? ^^ Das Setup ist, wenn man die Fallstricke erstmal überwunden hat (was ja dann schon der Fall wäre) ziemlich simpel. Ich hab's neulich in ca. ner halben Stunde wieder aufgesetzt bekommen auf ner frischen Installation vom Nano, damit der nicht mehr von SD sondern USB SSD bootet/läuft...

  • @Canis Nova der Gist dazu findet sich: hier (funktioniert im Moment nur mit MagentaTV)


    In den einzelnen Dateien steht jeweils in der ersten Zeile wo die Datei hingelegt werden muss. Die Zeile sollte dann entfernt werden.

    Die binary für den rtsp-simple-server kann hier heruntergeladen werden und muss in "/usr/local/bin/rtsp-simple-server" abgelegt werden (chmod +x nicht vergessen). Die Konfiguration rtsp-simple-server.yml entspricht bis auf die letzten 3 Zeilen dem Default (als Beispiel habe ich Pro7 via MagentaTV hinterlegt). Da ich keine Möglichkeit gefunden habe, dass GStreamer selber ermittelt ob es ein Stream mit AC3 oder MP2 Audio ist hab ich das als Flag ergänzt ("-a", default ist "mp2", ansonsten "ac3" eintragen), welcher manuell (aber immerhin ja einmalig) hinterlegt werden muss.

    Der rtsp-simple-server.service muss natürlich noch via systemd aktiviert und gestartet werden.

    stream.start (startet die GStreamer Pipeline und published dann auf den rtsp-simple-server) wird onDemand vom rtsp-simple-server aufgerufen und startet von sich aus auch stream.dump - was lediglich den originalstream abruft und die Pakete so aufbereitet, dass GStreamer damit arbeiten kann. Letzteres könnte man z.B. für andere Quellen (als MagentaTV) auch via FFMPEG machen, dann sind die Umschaltzeiten aber nochmal wieder ein ganzes Stück länger.

    Edit: Da hab ich doch glatt die Installation der Entrans-Filter vergessen... Hier ein Beispiel wie man das installiert bekommt so das es funktioniert.

    Ist das alles eingerichtet und gestartet, dann kann man in TVHeadend ein neues Network anlegen und dazu dann einen Mux mit folgender URL einrichten (zunächst die originale Stream-URL eintragen, damit der Scan durchläuft):

    rtp://232.0.10.120:10000?sources=87.141.215.251

    Wenn das erledigt ist, kann man die folgende Pipeline hinterlegen (muss leider durch FFMPEG, da TVHeadend RTSP nur sehr rudimentär unterstützt):

    pipe:///usr/bin/ffmpeg -loglevel fatal -hide_banner -nostdin -nostats -i rtsp://xxx.xxx.xxx.xxx:8554/pro7 -c:v copy -c:a copy -metadata service_name=ProSieben -metadata service_provider=Nano -mpegts_service_type advanced_codec_digital_sdtv -f mpegts pipe:1

    Das war jetzt mal die extreme Kurzfassung (bin im Moment leider ziemlich überlastet) - bei Fragen: Fragen ;)

    GitHub Repo: Easyepg.minimal
    Docker Hub: Easyepg.minimal, Telerising.minimal
    Bierspende: PayPal.Me :thumbup:

    Geräte: AWOL Vision LTV-3000 Pro, ES Aeon Starbright CLR 90", NVIDIA Shield TV Pro 2019, Cambridge Audio CXUHD
    Backend: PC Engines APU 2D4 (Docker: TVHeadend, Telerising, Easyepg, Deconz, OpenHAB)

    3 Mal editiert, zuletzt von dlueth (2. März 2021 um 22:46)

  • Wenn es zeitlich mal wieder besser aussieht werde ich mich nochmal damit auseinandersetzen so etwas für das deinterlacing auf dem Nano zu verwenden - wenn das klappt (keine Ahnung ob die Performance dafür reicht) dürfte es schwer zu toppen sein und wäre dann wohl im Ergbnis auch 576p@50 und nicht 576p@25, es würden also weniger Informationen "verloren" gehen...

  • So, ich hatte heute Abend etwas Zeit und habe mal mit dem Repo aus dem vorigen Post rumgespielt. Im Ergebnis klappt das deinterlacing damit, rein technisch. Allerdings würde ich Stand jetzt sagen, dass es nicht den Hauch einer Chance gibt das auf einem Jetson Nano in Echtzeit hinzubekommen, nicht mal für einen einzigen 576i Stream. Die FPS liegen (direkt aus dem Repo im Moment über ffmpeg, was nicht optimal ist - gstreamer hat halt die HW-Beschleunigung) so bei 1,5 und die GPU des Nanos ist zu 100% ausgelastet, permanent. Im Ergebnis hat man dann aber auch tatsächlich 576p50 und nicht 25, was natürlich eigentlich in der Theorie schön ist.

    Ich werd nochmal schauen ob und wenn ja wo man da tweaken kann, bin aber was den Nano angeht nicht sehr optimistisch. Spannend könnte es mit einem Xavier NX werden der spezielle Tensorcores hat - der ist aber preislich ne andere Hausnummer und was ich bisher so gelesen habe auch nicht gerade leise :(

    Mein bisheriges Setup steht ja aber so wie es ist und funktioniert auch wunderbar + das Bild ist imho für mich erstmal ausreichend und kein Vergleich mehr zu der Matsche die die Shield da beim Deinterlacing von Haus aus produziert

  • Ja, klar - alles andere würde im Leben nicht so gut laufen ;) meine jetzige Lösung basiert da drauf + ein bisschen was drumherum. Aber fürs letzte bisschen Bildqualität wollte ich halt Mal schauen an man das deinterlacing nicht mit ML noch besser hinbekommt...

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!