Scaling von cImage

  • Hallo kls,


    ich denke, du hast es nicht verfolgt, aber ausgehend von der Diskussion hier ist dieser Patch entstanden, der ein cImage um einen scalefactor erweitert. Damit ist es relativ einfach möglich, ein cImage skaliert zeichnen zu können. Für hardwarebasiertes OSD wäre das kein Mehraufwand.


    Wäre es denkbar, die Funktionalität so oder ähnlich in den Core aufzunehmen? Ein Problem sehe ich in der fehlenden Softwareimplementierung. Evtl. wäre es denkbar, das Feature nur anzubieten, wenn das ::DrawImage auch wirklich skalieren kann. Das könnte man über eine bool CanImageScale() einbauen. Das Skalieren ohne externe libs in Software zu machen ist wahrscheinlich nicht ohne.


    Für Bitmaps gibt es ja bereits DrawScaledBitmap(). Die Möglichkeit ein Image zu skalieren, würde die Lücke schließen und im Prinzip alle Möglichkeiten für hardwarebasiertes Rendering bieten.


    Wie denkst du darüber?


    Gruß

    Andreas

  • Der Usecase, in dem sich das als guter Weg zum Ziel erwiesen hat ist das vdr-plugin-web in Kombination mit cefbrowser und remotetranscode.


    cefbrowser und der transcoder bereiten hbbtv so auf, dass VDR sie über das web plugin mit Boardmitteln darstellen kann. Die drei Komponenten können auch auf verschiedenen Systemen laufen und schicken sich dann die Daten übers Netz. Soviel zum Grundsätzlichen.


    Bei der aktuellen Architektur holt sich der cefbrowser die hbbtv Seiten ab und stellt sie dem web plugin als ARGB zur Verfügung, das sie dann mit DrawImage ins OSD rendert. Der transcoder macht aus dem Video einen TS Stream, der von VDR direkt verarbeitet werden kann.

    Das ARGB könnte jetzt vom cefbrowser natürlich bereits in der richtigen Auflösung erstellt und verschickt werden. Heißt aber, dass man mit Software das Ausgangsbild von 1280x720 auf z.B. UHD skalieren muss und damit auch mehr Daten übers Netz gehen. Die Seiten so wie sie kommen zu verschicken und das Skalieren einer Osd-Methode zu überlassen, spart CPU, Datenmenge und am Ende Zeit. Die Ausgabeplugins, die mit OpenGL rendern, verwenden dieses ARGB/cImage intern am Ende als Texture und rendern es in der gewünschten Größe. Deshalb ist das Skalieren hier "umsonst". Ohne die Möglichkeit das cImage zu skalieren, funktioniert der Weg nicht.

    Bel der internen DrawImage Methode der GL Plugins gab es schon immer die Möglichkeit, factorX und factorY als Parameter zu übergeben (warum auch immer). Nur kann das bisher nicht genutzt werden, da sie von VDR Core nicht in der API angeboten werden.


    Ich sehe den großen Mehrwert darin, dass man hier relativ einfach die GPU nutzen kann und damit eigentlich alles mögliche mit ARGB Bildern anfangen kann und sie ohne Kosten skalieren kann. Praktisches Beispiel siehe oben. Anscheinend hat das bisher noch keiner vermisst, aber praktisch ist es hier. Evtl. ergeben sich noch weitere Anwendungsideen.


    Gruß

    Andreas

    Einmal editiert, zuletzt von rell ()

  • Passt. Ich habe jetzt nur mal versucht, ein argb per Software zu skalieren und mir ein kleines Beispielprogramm gebaut. Das ist von libyuv abgeschaut, nutzt aber keinerlei Optimierungen. Grundsätzlich funktioniert es, ein upscaling ist halt nicht überragen, das macht GL m.E. viel besser.

    cBitmap::Scaled() ist da ähnlich, ich glaube ein cImage::Scaled() würde ich auch hinkriegen.

    Oder sollte das ganze besser direkt in DrawScaledImage() ohne eine ::Scaled() Methode?


    Liege ich richtig, dass man am Ende

    Code
    cPixmap::DrawScaledImage(const cPoint &Point, const cImage &Image, double FactorX, double FactorY)
    cPixmap::DrawScaledImage(const cPoint &Point, int ImageHandle, double FactorX, double FactorY)
    cOsd::DrawScaledImage(const cPoint &Point, const cImage &Image, double FactorX, double FactorY)
    cOsd::DrawScaledImage(const cPoint &Point, int ImageHandle, double FactorX, double FactorY)

    implementieren muss? Sag mir, welcher Weg dir am liebsten wäre, dann versuche ich mich an einem Patch.

  • Hallo kls,


    ich habe mich mal an einem Patch versucht: https://github.com/rellla/VDRS…a9d23864249493af60c3aaefd


    Kompiliert, aber ich muss noch testen, ob er auch das macht was er soll.

    Wenn du Zeit übrig hast, könntest du mal überfliegen, ob die Richtung stimmt oder ob ich auf dem Holzweg bin.


    Ich bin mir als C++ Anfänger auch nicht sicher mit den pure virtual Methoden. Die müssten dann ja auch zwingend in allen Plugins, die die pixmap Klasse implementieren, vorhanden sein. Ansonsten bauen die nicht, oder? Gibt es hier einen eleganteren Weg?


    Gruß

    Andreas

  • So, ein wenig weiter...


    https://github.com/rellla/vdr/…6260f456106658d3d3885d765 wäre der Patch. Allerdings bekomme ich damit einen SEGV, den ich nicht richtig einordnen kann:

    Meine Debug-Logs laufen bis zum Ende unauffällig durch. Dennoch kommt der Fehler, den ich nur mit der Software-Implementierung habe. Mit OpenGL funktioniert es, daher schließe ich einen Fehler an den Patches fürs Ausgabeplugin etc. aus.

    Ich frage mich, was der Realloc in epg.c mit meinen Änderungen am OSD zu tun hat...


    Kann damit jemand was anfangen? Wahrscheinlich ist es nur eine kleine Sache, die ich nicht auf dem Schirm habe...

    Danke fürs Helfen.


    Gruß

    Andreas

  • Code
    Backtrace stopped: previous frame identical to this frame (corrupt stack?)

    Sieht schlecht aus :( .

    gdb kann Dir nicht helfen, den Fehler zu finden. Weil Speicher überschrieben wurde, den gdb bräuchte, um den Fehler zu finden ...

    Client1: ASUS P5QC, Dual Core 3G, Cine S2, Ext. Board von TBE, Xubuntu 20.04, VDR 2.6x

    Client2: RPI3

    Server: RPI4, Sundtek SkyTV Dual 2x

  • Fehler gefunden. Der Fehler liegt im Web-Plugin Zabrimus ;)

    tArea ist definiert durch x1, x2, y1 und y2.


    Damit kommt die Software-Implementierung von softhddevice-drm-gles (und evtl. auch die anderen) nicht zurecht. Hier wird der stride nicht mehr geändert, wenn die Viewport Größe noch mal angepasst wurde.

    Aber damit ist der SEGV weg. Werde später mal schauen, wie das Bild ist...


    Der aktuelle Stand zum Patch wäre hier.

  • Nachtrag: Der Patch scheint zu machen, was er soll :)

    Software Scaling funktioniert. Jetzt wäre die Frage, ob das so oder ähnlich in den Core kann...

  • Fehler gefunden. Der Fehler liegt im Web-Plugin

    Da bin ich schon wieder darauf reingefallen :( Warum Breite und Höhe 1 kleiner sein müssen, als gewünscht hat mir schon einmal Probleme gemacht.

    Hoffentlich hast du den seltenen Segfault gefunden, den ich bisher gar nicht finden konnte. Danke!


    Edit:

    Ach Mist. Ich bin schon wieder darauf hereingefallen :(

    Bei den möglichen Parametersätzen (x1, y1, x2, y2) zu (x, y, w, h) komme ich schnell durcheinander.

  • Ja, da muss man immer aufpassen :) War nicht leicht zu finden, trotzdem fehlt da noch was im Ausgabeplugin. w und h wird hier zwar gecroppt, aber stride wird danach nicht mehr geändert. Am Ende wird deswegen dann fremder Speicher überschrieben...

  • So, Patches für VDR und die softhddevice plugins sind hier in VDRSternELEC eingezogen. Ich hoffe, das gibt keine Nebenwirkungen, da ich nur für softhddevice-drm-gles testen konnte. Da klappt aber sowohl hardwarebasiertes DrawImageScaled als auch das Software-Fallback von VDR. Und bei letzterem kann man einen deutlichen Unterschied beim upscaling sehen, wenn AntiAlias gesetzt ist. Aber so soll es ja auch sein.


    Bisher einzige Anwendung ist vdr-plugin-web, die in VDRSternELEC das DrawImageScaled nutzt und womit man es testen kann. Produktiv sollte aber dringend AntiAlias gesetzt sein, da man sich das ansonsten nur von ganz weit weg ansehen kann ;) Evtl. macht es Sinn, AntiAlias auch gleich im Prototyp auf true zu setzen...


    kls: Würde mich freuen, wenn du die Funktionalität in den Core einbauen könntest...

Jetzt mitmachen!

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