如何从另一个线程调用Flutter Engine方法


9

我正在为Linux使用Flutter Desktop。我正在调用一个方法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而使用了Google的webrtc ,因此找不到它:https : //github.com/ JumpingYang001 / webrtc对我来说太大了,无法找到从何处调用OnFrame。但这一定是我从一个线程。这怎么可能?


如果您希望使用超时来替代在主运行循环中运行定期任务的方法,则可以提交Flutter引擎PR,以通过包装公开glfwPostEmptyEvent。有一种唤醒主运行循环的方法是对GLFW嵌入API的合理补充。
smorgan19年

@smorgan我会尝试的,但是我很惊讶这个例子:github.com/cloudwebrtc/flutter-webrtc/blob/desktop/common/src/…没有RunEventLoopWithTimeOut。由于他使用阻塞了主线程flutter_controller.RunEventLoop(),因此可以确定MarkTextureFrameAvailable必须从另一个线程中调用它,这是不可能的!
卢卡斯·扎内拉

在发表评论之前,请先快速警告-从未听说过Flutter,对Linux知之甚少,而且我在移动设备上,所以绝对现在不查看代码。希望我仍然可以提供帮助。:)您提供的示例的视频渲染器继承自主要的flutter渲染器实例。它们OnRender是Flutter的虚拟替代,因此被Flutter线程调用。
Pickle Rick

Answers:


3

请参阅我的评论以获取对此答案的警告。您提供的示例项目似乎可以通过一个简单的技巧来完成此任务。他们创建了一个新类,该类继承了flutter渲染器类,并OnFrame在其他方面进行了覆盖。当该覆盖被调用时,它在Flutter线程的上下文中,因此按预期工作。


非常感谢您的帮助!但是,Flutter的子类是Texture,没有onFrame方法的子类。该onFrame方法RTCVideoRenderer与Flutter无关。
卢卡斯·扎内拉

这里。看起来它们确实覆盖了Flutter,并且可能使用了受支持的插件系统。我最好的建议是阅读Flutter文档。我愿意打赌,如果您将BP放置在OnFrame中,则它会像预期的那样在Flutter线程的上下文中。
Pickle Rick

我在使用插件系统,并且已经阅读了文档,没有onFrame方法。FlutterVideoRenderer类中Flutter唯一的东西是Texture,它没有onFrame方法。其实我发现那里onFrame定义,距离的WebRTC图书馆的事情,你可以在这里看到github.com/JumpingYang001/webrtc/...
卢卡斯Zanella

@LucasZanella Pickle Rick是正确的,它FlutterVideoRenderer 继承自两个类- Texture(第16行)和RTCVideoRenderer<scoped_refptr<RTCVideoFrame>>(第17行)(C ++允许多重继承),然后它覆盖了OnFrame方法(第24行)。当OnFrame事件被触发,它在你的主线程的上下文中执行。
4LegsDrivenCat

@ 4LegsDrivenCat但OnFrame不是来自Flutter,它是来自RTCVideoRenderer,而不是Flutter
Lucas Zanella,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.