Как вызвать методы двигателя флаттера из другого потока

9

Я использую настольный компьютер для Linux. Я MarkTextureFrameAvailableвызываю метод, который должен пометить текстуру, которая должна быть обработана движком. Поскольку я программирую видеоплеер, мне нужно позвонить MarkTextureFrameAvailableиз ветки плеера. Проблема в том, что двигатель заставляет меня вызывать MarkTextureFrameAvailable(и любой другой метод двигателя) из потока, который создал двигатель.

Вы можете видеть, что все вызовы механизма заканчиваются в оболочке, которая всегда проверяет, выполняются ли вызовы из того же потока, который создал вызов:

task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()

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

Вот как я создаю движок флаттера:

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

Как вы можете видеть, поток, который создает движок, блокируется, и flutter_controller.RunEventLoop();это единственное место, где я мог бы разместить диспетчер событий, который заставлял вещи выполняться из потока main. Мне не нравится эта идея. Несмотря на то RunEventLoopWithTimeout, что существует, мне нужно поставить тайм-аут и продолжать проверять в очереди на MarkTextureFrameAvailableзвонки. Я не думаю, что это оптимально.

Так как мне звонить MarkTextureFrameAvailableиз основного потока?

Я нашел пример использования MarkTextureFrameAvailableздесь: https://github.com/cloudwebrtc/flutter-webrtc/blob/desktop/common/src/flutter_video_renderer.cc#L90, и похоже, что это другой поток, который вызывает его. Как это возможно? Когда я делаю, я получаю ФАТАЛЬНУЮ ошибку, но он делает, и это работает?

Я потратил два дня, пытаясь выяснить, какой поток вызывает OnFrame в этом примере, но не смог выяснить, потому что он использует https://github.com/flutter-webrtc/libwebrtc, который использует webrtc Google: https://github.com/ JumpingYang001 / webrtc, который слишком велик, чтобы я мог найти, откуда вызывается OnFrame. Но это должен я из нити. Как это возможно?

Лукас Занелла
источник
Если вы хотите использовать альтернативу тайм-ауту для запуска периодических задач в главном цикле выполнения, вы можете отправить PR движка Flutter для показа glfwPostEmptyEvent через оболочку. Возможность пробуждения основного цикла выполнения является разумным дополнением к API встраивания GLFW.
Сморган
@smorgan Я попробую это, но я удивлен, как этот пример: github.com/cloudwebrtc/flutter-webrtc/blob/desktop/common/src/… обходится без RunEventLoopWithTimeOut. Поскольку он блокирует основной поток с помощью flutter_controller.RunEventLoop(), то наверняка MarkTextureFrameAvailableдолжен быть вызван из другого потока, что должно быть невозможно!
Лукас Занелла
Быстрое предостережение перед моим комментарием - никогда не слышал о Flutter, очень мало знаю о Linux, и я нахожусь на мобильном телефоне, поэтому определенно не просматриваю код прямо сейчас. Надеюсь, я все еще могу помочь. :) В приведенном вами примере их рендерер видео наследуется от того, что выглядит как основной экземпляр рендера флаттера. Их OnRenderвиртуальное переопределение флаттера поэтому он получает вызывается нитью Flutter.
Рассол Рик

Ответы:

3

Смотрите мой комментарий для предупреждения к этому ответу. Похоже, что пример проекта, который вы предоставили, выполняет это с помощью простого трюка. Они создают новый класс, который наследует класс отрисовки флаттера, переопределяя OnFrameсреди прочего. Когда вызывается это переопределение, это происходит в контексте потока Flutter и работает так, как ожидалось.

Рассол Рик
источник
Большое спасибо за ваши усилия, чтобы помочь! Тем не менее, класс от Flutter, к Texture,которому относятся его подклассы , не имеет метода onFrame. Этот метод onFrame не RTCVideoRendererимеет ничего общего с Flutter.
Лукас Занелла,
Смотрите здесь . Похоже, они переопределяют Flutter и, возможно, используют поддерживаемую систему плагинов. Мой лучший совет - прочитать документацию Flutter. Я был бы готов поспорить, если бы вы поместили БП в OnFrame, это было бы в контексте потока Флаттера, как и ожидалось.
Рассол Рик
Я уже использую систему плагинов и прочитал документацию, метода onFrame нет. Единственное, что есть в Flutter в классе FlutterVideoRenderer - это Texture, у которого нет метода onFrame. На самом деле я нашел, где определено onFrame, и это вещь из библиотеки WebRTC, как вы можете видеть здесь github.com/JumpingYang001/webrtc/…
Лукас Занелла
@LucasZanella Пикл Рик прав, FlutterVideoRenderer наследует от двух классов - Texture(строка 16) и RTCVideoRenderer<scoped_refptr<RTCVideoFrame>>(строка 17) (C ++ допускает множественное наследование), а затем переопределяет OnFrameметод (строка 24). Когда OnFrameсобытие запускается, оно выполняется в контексте вашего основного потока.
4LegsDrivenCat
@ 4LegsDrivenCat, но OnFrame не от Flutter, а от RTCVideoRenderer, а не от Flutter
Лукас Занелла