Tone Mapping HDR-Helligkeit in einem SDR-kompatiblen Bereich

Mit Android 13 wird eine vom Anbieter konfigurierbare statische Bibliothek namens libtonemap eingeführt, die Tonzuordnungsvorgänge definiert und mit den SurfaceFlinger-Prozess- und HWC-Implementierungen (Hardware Composer) geteilt wird. Mit dieser Funktion können OEMs ihre Display-Tonmapping-Algorithmen zwischen dem Framework und den Anbietern definieren und teilen, um Abweichungen bei der Tonzuordnung zu verringern.

Vor Android 13 wurden anzeigespezifische Tone Mapping-Vorgänge nicht von HWC, SurfaceFlinger und Apps gemeinsam genutzt. Je nach Renderingpfad führte dies bei HDR-Inhalten zu Abweichungen bei der Bildqualität, da die HDR-Inhalte auf unterschiedliche Weise in einen Ausgaberaum umgewandelt wurden. Dies war z. B. in Szenarien wie der Bildschirmdrehung wahrnehmbar, bei denen sich die Kompositionsstrategie zwischen GPU und DPU änderte, und in Unterschieden beim Renderingverhalten zwischen TextureView und SurfaceView.

Auf dieser Seite werden die Benutzeroberfläche, die Anpassung und die Validierung der libtonemap-Bibliothek beschrieben.

Schnittstelle für die Tone Mapping-Bibliothek

Die Bibliothek libtonemap enthält CPU-gestützte Implementierungen und SkSL-Shader, die von SurfaceFlinger für die GPU-Back-End-Zusammensetzung und von der HWC zum Generieren einer Tone Mapping-Lookup-Tabelle (LUT) eingebunden werden können. Der Einstiegspunkt für libtonemap ist android::tonemap::getToneMapper(). Diese Funktion gibt ein Objekt zurück, das die Schnittstelle ToneMapper implementiert.

Die ToneMapper-Schnittstelle unterstützt die folgenden Funktionen:

  • Tone-Mapping-LUT generieren

    Die Schnittstelle ToneMapper::lookupTonemapGain ist eine CPU-Implementierung des in libtonemap_LookupTonemapGain() definierten Shaders. Dieser wird von Unit-Tests im Framework verwendet und kann von Partnern zur Unterstützung beim Generieren einer Tonmapping-LUT in ihrer Farbpipeline verwendet werden.

    libtonemap_LookupTonemapGain() nimmt Farbwerte im absoluten, nicht normalisierten linearen Raum sowohl in linearem RGB als auch in XYZ entgegen und gibt einen Float-Wert zurück, der angibt, um wie viel die Eingabefarben im linearen Raum multipliziert werden sollen.

  • SkSL-Shader generieren

    Die Schnittstelle ToneMapper::generateTonemapGainShaderSkSL() gibt einen SkSL-Shaderstring mit einem Quell- und Zieldatenraum zurück. Der SkSL-Shader ist in die Skia-Implementierung für RenderEngine eingesteckt, die GPU-beschleunigte Compositing-Komponente für SurfaceFlinger. Der Shader ist auch mit libhwui verbunden, damit das HDR-zu-SDR-Tone Mapping für TextureView effizient durchgeführt werden kann. Da der generierte String in andere von Skia verwendete SkSL-Shader eingebettet ist, muss der Shader den folgenden Regeln entsprechen:

    • Der Shader-String muss einen Einstiegspunkt mit der Signatur float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz) haben. Dabei ist linearRGB der Wert der absoluten Nits der RGB-Pixel im linearen Raum und xyz ist linearRGB in XYZ umgewandelt.
    • Allen vom Shader-String verwendeten Hilfsmethoden muss der String libtonemap_ vorangestellt werden, damit Framework-Shaderdefinitionen nicht in Konflikt stehen. Ebenso müssen Eingabeuniformen das Präfix in_libtonemap_ haben.
  • SkSL-Uniformen generieren

    Die Schnittstelle ToneMapper::generateShaderSkSLUniforms() gibt Folgendes zurück, wenn ein Metadaten-struct angegeben ist, das Metadaten aus verschiedenen HDR-Standards und Anzeigebedingungen beschreibt:

    • Eine Liste von Uniformen, die an einen SkSL-Shader gebunden sind.

    • Die einheitlichen Werte in_libtonemap_displayMaxLuminance und in_libtonemap_inputMaxLuminance. Diese Werte werden von Framework-Shadern verwendet, wenn die Eingabe nach libtonemap skaliert und die Ausgabe entsprechend normalisiert wird.

    Derzeit ist der Prozess der Uniformerstellung unabhängig vom Ein- und Ausgabedatenraum.

Personalisierung

Die Referenzimplementierung der libtonemap-Bibliothek liefert akzeptable Ergebnisse. Da sich der von der GPU-Zusammensetzung verwendete Tonzuordnungsalgorithmus jedoch von dem der DPU-Zusammensetzung unterscheiden kann, kann die Verwendung der Referenzimplementierung in einigen Szenarien, z. B. bei der Rotationsanimation, zu Flackern führen. Mithilfe von Anpassungen können solche anbieterspezifischen Probleme mit der Bildqualität behoben werden.

OEMs wird dringend empfohlen, die Implementierung von libtonemap zu überschreiben, um eine eigene ToneMapper-Unterklasse zu definieren, die von getToneMapper() zurückgegeben wird. Bei der Anpassung der Implementierung müssen Partner einen der folgenden Schritte ausführen:

  • Implementierung von libtonemap direkt ändern.
  • Sie können eine eigene statische Bibliothek definieren, die Bibliothek als eigenständiges Programm kompilieren und die Datei .a der libtonemap-Bibliothek durch die aus der benutzerdefinierten Bibliothek generierte Datei ersetzen.

Anbieter müssen keinen Kernelcode ändern, aber mehrere Anbieter müssen Details zu den DPU-Tone-Mapping-Algorithmen für eine ordnungsgemäße Implementierung kommunizieren.

Zertifizierungsstufe

So prüfen Sie Ihre Implementierung:

  1. Spielen Sie HDR-Videos auf Bildschirmen mit HDR-Standards ab, die Ihr Anzeigesystem unterstützt, z. B. HLG, HDR10, HDR10+ oder DolbyVision.

  2. Aktivieren oder deaktivieren Sie die GPU-Komposition, damit kein für den Nutzer wahrnehmbares Flimmern auftritt.

    Verwenden Sie den folgenden adb-Befehl, um die GPU-Zusammensetzung ein-/auszuschalten:

    adb shell service call SurfaceFlinger 1008 i32 <0 to enable HWC composition,
    1 to force GPU composition>
    
    

Häufige Probleme

Bei dieser Implementierung können folgende Probleme auftreten:

  • Banding tritt auf, wenn das von der GPU-Zusammensetzung verwendete Renderingziel eine geringere Genauigkeit aufweist als der typische Wert für HDR-Inhalte. Zum Beispiel kann Banding auftreten, wenn eine HWC-Implementierung opaker 10-Bit-Formate für HDR wie RGBA1010102 oder P010 unterstützt, aber die GPU-Zusammensetzung in ein 8-Bit-Format wie RGBA8888 schreibt, um Alpha zu unterstützen.

  • Eine subtile Farbverschiebung wird durch Quantisierungsunterschiede verursacht, wenn die DPU mit einer anderen Genauigkeit als die GPU arbeitet.

Jedes dieser Probleme hängt mit den relativen Differenzen bei der Genauigkeit der zugrunde liegenden Hardware zusammen. Eine gängige Lösung besteht darin, in den Pfaden mit niedrigerer Präzision einen Dithering-Schritt vorzusehen, wodurch Abweichungen bei der Präzision für den Betrachter weniger wahrnehmbar sind.