Jak wywołać metody silnika trzepotania z innego wątku

9

Używam trzepotania pulpitu dla Linuksa. Nazywam metodę o nazwie, MarkTextureFrameAvailablektóra ma oznaczać teksturę do ponownego wysłania przez silnik. Ponieważ programuję odtwarzacz wideo, muszę dzwonić MarkTextureFrameAvailablez wątku odtwarzacza. Problem polega na tym, że silnik zmusza mnie do wywołania MarkTextureFrameAvailable(i dowolnej innej metody silnika) z wątku, który utworzył silnik.

Możesz zobaczyć, że wszystkie wywołania silnika kończą się w powłoce, która zawsze sprawdza, czy połączenia są wykonywane z tego samego wątku, który utworzył połączenie:

task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()

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

Oto jak tworzę silnik trzepotania:

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;
}

jak widać, wątek tworzący silnik zostaje zablokowany przez flutter_controller.RunEventLoop();to jedyne miejsce, w którym mogłem umieścić dyspozytora zdarzeń, który wymusił wykonanie rzeczy z wątku głównego. Nie podoba mi się ten pomysł. Mimo że RunEventLoopWithTimeoutistnieje, muszę ustawić limit czasu i sprawdzać kolejkę MarkTextureFrameAvailablepołączeń. Nie sądzę, żeby to było optymalne.

Jak mam zadzwonić MarkTextureFrameAvailablez głównego wątku?

Znalazłem przykład użycia MarkTextureFrameAvailabletutaj: https://github.com/cloudwebrtc/flutter-webrtc/blob/desktop/common/src/flutter_video_renderer.cc#L90 i wygląda na to, że to kolejny wątek, który to nazywa. Jak to jest możliwe? Kiedy to robię, pojawia się FATALNY błąd, ale on robi i to działa?

Spędziłem dwa dni, próbując dowiedzieć się, który wątek wywołuje OnFrame w tym przykładzie, ale nie mogłem się dowiedzieć, ponieważ używa https://github.com/flutter-webrtc/libwebrtc, który używa Google webrtc: https://github.com/ JumpingYang001 / webrtc, który jest dla mnie za duży, aby znaleźć skąd pochodzi OnFrame. Ale to musi mnie z wątku. Jak to jest możliwe?

Lucas Zanella
źródło
Jeśli chcesz skorzystać z opcji limitu czasu do uruchamiania okresowych zadań w głównej pętli uruchomieniowej, możesz przesłać PR silnika Flutter, aby ujawnić glfwPostEmptyEvent za pośrednictwem opakowania. Sposób budzenia głównego runloopa jest rozsądnym dodatkiem do interfejsu API do osadzania GLFW.
smorgan
@smorgan Spróbuję tego, ale jestem zdumiony tym, jak ten przykład: github.com/cloudwebrtc/flutter-webrtc/blob/desktop/common/src/… nie działa bez RunEventLoopWithTimeOut. Skoro blokuje główny wątek flutter_controller.RunEventLoop(), to na pewno MarkTextureFrameAvailablemusi zostać wywołany z innego wątku, co powinno być niemożliwe!
Lucas Zanella
Szybkie ostrzeżenie przed moim komentarzem - nigdy nie słyszałem o Flutter, niewiele wiem o Linuksie, a ja korzystam z urządzeń mobilnych, więc zdecydowanie nie przeglądam teraz kodu. Mam nadzieję, że nadal mogę pomóc. :) Podany przez Ciebie przykład ma mechanizm renderujący wideo dziedziczący z czegoś, co wygląda jak główna instancja mechanizmu renderującego trzepotanie. Ich OnRenderjest wirtualnym zastąpieniem Fluttera, więc jest wywoływany przez wątek Fluttera.
Pickle Rick

Odpowiedzi:

3

Zobacz mój komentarz dotyczący zastrzeżenia do tej odpowiedzi. Wygląda na to, że przykładowy projekt, który podałeś, realizuje to w prosty sposób. Tworzą nową klasę, która dziedziczy klasę renderującą trzepotanie, zastępując OnFramemiędzy innymi. Wywołanie tego zastąpienia następuje w kontekście wątku Flutter i działa zgodnie z oczekiwaniami.

Pickle Rick
źródło
Dziękuję bardzo za twój wysiłek, aby pomóc! Jednak klasa z trzepotanie że jest podklas Texture,, które nie mają onFrame metody. Ta metoda onFrame RTCVideoRenderernie ma nic wspólnego z Flutter.
Lucas Zanella
Zobacz tutaj . Wygląda na to, że zastępują Flutter i prawdopodobnie używają obsługiwanego systemu wtyczek. Moja najlepsza rada to przeczytanie dokumentacji Fluttera. Byłbym skłonny postawić, jeśli umieścisz BP w OnFrame, będzie to zgodnie z oczekiwaniami w kontekście wątku Flutter.
Pickle Rick,
Aleady używam systemu wtyczek i przeczytałem dokumentację, nie ma metody onFrame. Jedyną rzeczą z Flutter w klasie FlutterVideoRenderer jest Texture, która nie ma metody onFrame. Właściwie znalazłem, gdzie jest zdefiniowany onFrame, i jest to rzecz z biblioteki WebRTC, jak można zobaczyć tutaj github.com/JumpingYang001/webrtc/…
Lucas Zanella
@LucasZanella Pickle Rick ma rację, FlutterVideoRenderer dziedziczy z dwóch klas - Texture(linia 16) i RTCVideoRenderer<scoped_refptr<RTCVideoFrame>>(linia 17) (C ++ pozwala na wielokrotne dziedziczenie), a następnie zastępuje OnFramemetodę (linia 24). Po OnFrameuruchomieniu zdarzenia jest ono wykonywane w kontekście głównego wątku.
4LegsDrivenCat
@ 4LegsDrivenCat, ale OnFrame nie jest od Fluttera, to od RTCVideoRenderer, który nie jest od Fluttera
Lucas Zanella