MediaCodec mit dem Surface Input: Aufnahme im hintergrund

Arbeite ich an einem video-encoding-Anwendung, die ich will, um zu verhindern, dass aus beenden, wenn die hosting-Aktivität tritt in den hintergrund, oder der Bildschirm Zyklen ein - /ausschalten.

Die Architektur der mein encoder stammt von der ausgezeichneten CameraToMpegTest Beispiel, mit dem Zusatz, der die Anzeige von frames zu einem GLSurfaceView (siehe Github-links unten). Ich bin derzeit die Aufzeichnung im hintergrund mit einer zwei-Staaten-Lösung:

  • Wenn der hosting-Tätigkeit ist im Vordergrund, codieren Sie einen video-frame, das bei jedem Aufruf der GLSurfaceView.Renderer's onDrawFrame. Dies ermöglicht mir den Zugriff auf die GLSurfaceView ist die EGL Staat in bursts so nicht zu blockieren, andere events in der Warteschlange des renderer-thread.

  • Wenn der hosting-Tätigkeit tritt in den hintergrund, halt die onDrawFrame Codierung und Encodierung von frames auf einer anderen hintergrund-thread in einer Schleife. Dieser Modus ist identisch mit dem CameraToMpegTest Beispiel.

Jedoch, wenn der Bildschirm ausgeschaltet ist, die GLSurfaceView ist EGLContext verloren und einen neuen Anruf zu onSurfaceCreated Auftritt. In diesem Fall haben wir neu erstellen, die EGL-Fenster-Oberfläche verbunden mit MediaCodec input-Oberfläche. Leider ist diese 2. Aufruf eglCreateWindowSurface produziert:

E/libEGL(18839): EGLNativeWindowType 0x7a931098 already connected to another API

Vor anrufen, ich lassen Sie alle EGL-Ressourcen, verbunden mit der Android-Oberfläche.

Gibt es eine Möglichkeit, tauschen Sie die EGLSurface verbunden mit MediaCodec input-Oberfläche?

Den vollständigen source von meinem test-Anwendung ist auf Github. Haupttätigkeit.

Update ich wandte die Lektionen, die hier gelernt in einem video-sdk für Android basierend auf den MediaCodec & MediaMuxer Klassen. Hoffe, es hilft!

  • MediaCodec sollte nicht betroffen sein (oder sogar bewusst) seins in den hintergrund. Siehe z.B. die screenrecord Befehl Hinzugefügt, die in Android 4.4, die gerne läuft hinter den kulissen. Die Tatsache, dass es Codierung nichts bedeutet, es ist immer noch die input-Daten, somy Vermutung wäre, dass etwas ist, die Camera. Ich verstehe nicht, warum es verursachen würde, die Vorschau Surface leer zu sein, während die Vorschau byte[] hat echten Daten.
  • Aktualisiert meine Frage. Ich bin jetzt in der Lage, den übergang zum hintergrund der Aufnahme (keine GLSurfaceView display) und dann Vorder-Aufnahme (GLSurfaceView display) außer, wenn ein Bildschirm aus/ein Ereignis tritt in der Zwischenzeit...
  • Ihnen fehlt ein glSurfaceView.onPause() in Ihrer Haupttätigkeit onPause(). Nicht sicher, ob das gleich, obwohl. Vielleicht kann ich mit ihm spielen ein bisschen, und morgen sehen, ob ich replizieren kann, das Verhalten.
  • Die Aktivität onPause() eine Methode aufruft, verwendet glSurfaceView.queueEvent() Warteschlange eine operation erfolgen muss, der auf den renderer thread, bevor glSurfaceView.onPause() hält es. Siehe hier
  • Bildschirm off/on bewirkt, dass die GLSurfaceView ist EGLContext verloren, wir haben also eine neue zu erstellen CodecInputSurface.mEGLSurface, dass die Aktien des neuen EGLContext. Jedoch Probleme beim trennen der MediaCodec input Oberfläche zu vermeiden already connected to another API Fehler auf eglCreateWindowSurface. Sollte dies möglich sein?
  • Schnell dachte: developer.android.com/reference/android/opengl/...
  • Ich habe setPreserveEGLContextOnPause set true. Funktioniert, bis der Bildschirm ausgeschaltet Konfigurationsänderung bewirkt, dass onDestroy(). Freigeben wollen, diese als Bibliothek, so dass nicht wollen, verlangen von Entwicklern Griff Konfigurationsänderungen manuell. Im schlimmsten Fall kann ich den swap in eine neue MediaCodec und update der Oberfläche.
  • Blick auf ~egl_surface_t im frameworks/native/opengl/libs/EGL/egl_object.cpp, der früheren EGL Oberfläche trennen soll aus dem MediaCodec Eingabe-Oberfläche, wenn es zerstört wird (eglDestroySurface + eglMakeCurrent(nichts)). Eine Sache, die Sie tun könnten, ist, prüft CodecInputSurface Methoden... rufen eglGetCurrentContext und sehen, ob es .equal() zu mEGLEncodeContext um zu bestätigen, dass der richtige Kontext ist eine aktuelle, wenn Sie zerstören+eglMakeCurrent (nicht das "=="). Die Oberfläche wird nicht zerstört werden, wenn es noch aktuell in einem verwaisten Kontext.
  • Was sollte ich gesagt habe, ist: stellen Sie sicher, dass Sie in den richtigen thread, wenn Sie anrufen eglMakeCurrent(nothing). Wenn der Kontext " +thread ist der aktuelle thread #1, dann ruft eglMakeCurrent(nothing) im thread #2 nicht loslassen den Faden und Fläche. Wenn der thread den aktuellen Kontext entspricht, was Sie in das Objekt, dann wissen Sie, Sie sind an der richtigen Stelle. (Es sei denn, Sie haben die gleichen aktuellen Kontext in zwei verschiedenen threads, in dem Fall wirst du in eine Welt von weh.)
  • FWIW, ich habe etwas ähnliches arbeiten über power-Zyklus auf einem Nexus 5. Mein encoder-thread bekommt eine Nachricht mit der neuen GLSurfaceView EGLSurface, und fordert den Gegenwert von releaseAllButSurface() + eglSetup() + SurfaceTextureManager.surfaceCreated(). Meine app geht nur um zu schlafen, während die Stromversorgung ausgeschaltet ist, so dass Sie am Ende mit einer langen pause in der Aufnahme, aber es wählt rechts, wenn die app fortgesetzt wird.

InformationsquelleAutor dbro | 2013-11-26
Schreibe einen Kommentar