Wie kann ich direkt von Android Surface auf EGL Image zugreifen, um es im MediaCodec-Videodecoder zu verwenden?

8

Ich schreibe gerade eine Android-App, wo ich Video-Frames zwischenspeichern muss, damit ich leicht und ohne Verzögerung hin und her gehen kann.

Im Moment lasse ich Android den Videoframe dekodieren, indem ich eine Oberfläche für den Aufruf des Objekts MediaCodec bereitstelle und releaseOutputBuffer aufruft, wobei das Render-Flag auf true gesetzt ist.

Die einzige Möglichkeit, auf die decodierten Oberflächendaten zuzugreifen (neben der Dekodierung des zurückgegebenen Bytepuffers, dessen Format anscheinend geräteabhängig ist) ist, updateTeximage auf der SurfaceTexture zu verwenden, die mit der Oberfläche verbunden ist. co_de% target und rendering es zu einem GL_TEXTURE_EXTERNAL_OES target texture Ich habe mich selbst erstellt, um es zu cachen.

Ich möchte diesen Caching-Prozess optimieren und die Frames in einem anderen Thread dekodieren können. Wenn ich meine aktuelle Methode benutze, müsste ich einen anderen EGL-Kontext für den Videodecoder erstellen, den Kontext teilen ...

Meine Frage ist: Ist es möglich, auf die EGL-Image- oder nativen Pufferdaten zuzugreifen, die mit der Surface verknüpft sind, ohne GL_TEXTURE2D aufzurufen?

Auf diese Weise konnte ich das Egl-Image zwischenspeichern (das erfordert keinen EGL-Kontext nach updateTexImage ). Dies würde auch im YUV-Format zwischengespeichert werden, was viel speichereffizienter wäre als die rohen RGB-Texturen, die ich jetzt cache.

    
Nico Cornelis 12.09.2013, 15:39
quelle

1 Antwort

4

Kurze Antwort: Nein.

Längere Antwort: Das Surface kapselt ein Warteschlange der Puffer . ( Bearbeiten: Das System wird nun im Detail hier erläutert.) Wann Sie rufen updateTexImage() auf, wenn ein neuer Datenrahmen verfügbar ist, wird der Puffer am Kopf gelöscht und der nächste in der Warteschlange wird aktuell. Aufruf von updateTexImage() ist notwendig, um aufeinanderfolgende Frames zu sehen; Es gibt keinen Mechanismus zum Untersuchen von Puffern, die nicht am Kopf sind.

A SurfaceTexture umschließt eine Instanz von GLConsumer . Dieser Verbraucher benötigt den Erzeuger (den Videodekoder), um Daten in einem Format zu erzeugen, das als eine "Hardwarebeschaffenheit" verwendet werden kann, d.h. etwas, das die GL-Implementierung des Geräts verstehen kann. Es kann oder kann nicht YUV sein. Um es noch genauer zu sagen, der Verbraucher benötigt nicht, dass der Puffer für "Software" verfügbar ist, was bedeutet, dass Sie nicht davon ausgehen können, dass Sie direkt auf die Daten zugreifen können - Sie müssen GLES verwenden. (Siehe den gralloc-Header Liste der Flaggen.)

Was wäre schön hier ist die Möglichkeit, den Puffer vom Kopf des BufferQueue in eine separate Datenstruktur ( BufferArrayList ?) zu kopieren, ohne eine Formatkonvertierung durchzuführen, aber es gibt keinen solchen Mechanismus bei Geschenk (Android 4.3). Ich kenne keinen besseren Weg als das, was Sie beschreiben (gemeinsame EGL-Kontexte usw.).

Update: Mein Bürokollege hatte einen Vorschlag: Verwende einen Shader, um den Puffer in zwei Texturen zu rendern, eine für Y und CbCr (in GLES 3 kannst du eine RG-Textur verwenden). Dadurch bleiben alle Manipulationen in GLES erhalten, ohne sich in RGB zu erweitern. Intern konvertiert es die MediaCodec -Ausgabe in RGB und mahlt es zweimal durch, aber das ist wahrscheinlich billiger, als es in den Userspace zu kopieren und es selbst auf der CPU zu tun.

    
fadden 12.09.2013, 20:10
quelle