So rufen Sie Flatter-Engine-Methoden aus einem anderen Thread auf

9

Ich benutze Flutter Desktop für Linux. Ich rufe eine Methode namens aufMarkTextureFrameAvailable , die eine Textur markieren soll, die von der Engine erneut gerendert werden soll. Da ich einen Videoplayer programmiere, muss ich über MarkTextureFrameAvailableden Thread des Players aufrufen . Das Problem ist, dass die Engine mich zwingt, MarkTextureFrameAvailable(und jede andere Engine-Methode) von dem Thread aus aufzurufen, der die Engine erstellt hat.

Sie können sehen, dass alle Aufrufe der Engine in der Shell landen, die immer prüft, ob die Aufrufe von demselben Thread stammen, der den Aufruf erstellt hat:

task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()

( https://github.com/flutter/engine/blob/master/shell/common/shell.cc#L838 )

So erstelle ich die Flatter-Engine:

int main(int argc, char **argv) {
  //..

  flutter::FlutterWindowController flutter_controller(icu_data_path);

  // Start the engine.
  if (!flutter_controller.CreateWindow(800, 600, "Flutter WebRTC Demo", assets_path,
                                       arguments)) {
    return EXIT_FAILURE;
  }

  // Register any native plugins.
  FlutterWebRTCPluginRegisterWithRegistrar(
      flutter_controller.GetRegistrarForPlugin("FlutterWebRTCPlugin"));

  // Run until the window is closed.
  flutter_controller.RunEventLoop();
  return EXIT_SUCCESS;
}

Wie Sie sehen können, wird der Thread, der die Engine erstellt, blockiert. flutter_controller.RunEventLoop();Dies ist der einzige Ort, an dem ich einen Ereignis-Dispatcher platzieren kann, der die Ausführung von Dingen aus dem Haupt-Thread erzwingt. Diese Idee gefällt mir nicht. Obwohl RunEventLoopWithTimeoutvorhanden, muss ich eine Zeitüberschreitung festlegen und weiterhin in einer Warteschlange nach MarkTextureFrameAvailableAnrufen suchen . Ich denke nicht, dass dies optimal ist.

Wie soll ich MarkTextureFrameAvailablevom Haupt-Thread aus aufrufen ?

Ich habe hier ein Anwendungsbeispiel MarkTextureFrameAvailablegefunden: https://github.com/cloudwebrtc/flutter-webrtc/blob/desktop/common/src/flutter_video_renderer.cc#L90 und es sieht so aus, als wäre es ein anderer Thread, der es aufruft. Wie ist es möglich? Wenn ich das tue, bekomme ich einen FATAL-Fehler, aber er tut es und es funktioniert?

Ich habe zwei Tage lang versucht herauszufinden, welcher Thread OnFrame in diesem Beispiel aufruft, konnte es aber nicht herausfinden, da er https://github.com/flutter-webrtc/libwebrtc verwendet, das Googles Webrtc verwendet: https://github.com/ JumpingYang001 / webrtc, das zu groß für mich ist, um herauszufinden, woher OnFrame kommt. Aber es muss mir aus einem Thread. Wie ist es möglich?

Lucas Zanella
quelle
Wenn Sie eine Alternative zur Verwendung eines Timeouts zum Ausführen periodischer Aufgaben im Haupt-Runloop wünschen, können Sie eine Flutter-Engine-PR senden, um glfwPostEmptyEvent über einen Wrapper verfügbar zu machen. Die Möglichkeit, den Haupt-Runloop zu aktivieren, ist eine sinnvolle Ergänzung der GLFW-Einbettungs-API.
Smorgan
@smorgan Ich werde das versuchen, aber ich bin erstaunt, wie dieses Beispiel: github.com/cloudwebrtc/flutter-webrtc/blob/desktop/common/src/… ohne RunEventLoopWithTimeOut auskommt. Da er den Haupt-Thread mit blockiert flutter_controller.RunEventLoop(), MarkTextureFrameAvailablemuss er sicher von einem anderen Thread aufgerufen werden, was unmöglich sein sollte!
Lucas Zanella
Kurze Einschränkung vor meinem Kommentar - ich habe noch nie von Flutter gehört, weiß sehr wenig über Linux und bin auf dem Handy, also schaue ich den Code momentan definitiv nicht durch. Hoffentlich kann ich trotzdem helfen. :) In dem Beispiel, das Sie gegeben haben, erbt der Video-Renderer von der Hauptinstanz des Flatter-Renderers. Es OnRenderhandelt sich um eine virtuelle Überschreibung von Flutter, sodass es vom Flutter-Thread aufgerufen wird.
Pickle Rick

Antworten:

3

Siehe meinen Kommentar für die Einschränkung dieser Antwort. Es scheint, dass das von Ihnen bereitgestellte Beispielprojekt dies mit einem einfachen Trick erreicht. Sie erstellen eine neue Klasse, die die Flatter-Renderer-Klasse erbt und OnFrameunter anderem überschreibt . Wenn diese Überschreibung aufgerufen wird, befindet sie sich im Kontext des Flutter-Threads und funktioniert wie erwartet.

Gurke Rick
quelle
Vielen Dank für Ihre Hilfe! Die Klasse von Flutter, die in Unterklassen unterteilt ist Texture,, verfügt jedoch nicht über die onFrame-Methode. Diese onFrame-Methode RTCVideoRendererhat nichts mit Flutter zu tun.
Lucas Zanella
Siehe hier . Sieht so aus, als würden sie Flutter überschreiben und möglicherweise ein unterstütztes Plugin-System verwenden. Mein bester Rat wäre, die Flutter-Dokumentation zu lesen. Ich würde wetten, wenn Sie einen BP in OnFrame platzieren würden, würde dies erwartungsgemäß im Kontext des Flutter-Threads erfolgen.
Pickle Rick
Ich benutze bereits das Plugin-System und habe die Dokumentation gelesen. Es gibt keine onFrame-Methode. Das einzige, was Flutter in der FlutterVideoRenderer-Klasse enthält, ist Texture, das keine onFrame-Methode hat. Eigentlich habe ich herausgefunden, wo onFrame definiert ist und ist eine Sache aus der WebRTC-Bibliothek, wie Sie hier sehen können. Github.com/JumpingYang001/webrtc/…
Lucas Zanella
@LucasZanella Pickle Rick hat recht, FlutterVideoRenderer erbt von zwei Klassen - Texture(Zeile 16) und RTCVideoRenderer<scoped_refptr<RTCVideoFrame>>(Zeile 17) (C ++ erlaubt Mehrfachvererbung) und überschreibt dann die OnFrameMethode (Zeile 24). Wenn ein OnFrameEreignis ausgelöst wird, wird es im Kontext Ihres Hauptthreads ausgeführt.
4LegsDrivenCat
@ 4LegsDrivenCat, aber OnFrame ist nicht von Flutter, es ist von RTCVideoRenderer, das nicht von Flutter ist
Lucas Zanella