Summary
The flutter_webrtc plugin does not work with flutter-pi due to a main loop incompatibility. The plugin's Linux implementation uses GLib's g_main_context_invoke() for thread marshalling, but flutter-pi uses libsystemd's sd-event loop instead.
Environment
- Device: Raspberry Pi 5
- flutter-pi version: latest from source
- flutter_webrtc version: 0.12.12
- Flutter SDK: 3.10.7
Error Output
[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: Call initialize before setting the stream
#0 RTCVideoRenderer.srcObject= (package:flutter_webrtc/src/native/rtc_video_renderer_impl.dart:61)
#1 WebRtc._cleanup (package:frame_client/features/agent/providers/webrtc_provider.dart:395)
<asynchronous suspension>
[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: WebSocketChannelException: SocketException: Connection refused (OS Error: Connection refused, errno = 111), address = localhost, port = 37130
[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: WebSocketChannelException: SocketException: Connection refused (OS Error: Connection refused, errno = 111), address = localhost, port = 42876
The random high ports (37130, 42876, etc.) suggest libwebrtc's internal networking fails during ICE candidate gathering because initialization callbacks never complete.
Root Cause Analysis
The flutter_webrtc plugin's Linux implementation relies on GLib for thread marshalling in task_runner_linux.cc:
void TaskRunnerLinux::EnqueueTask(TaskClosure task) {
// ...
GMainContext* context = g_main_context_default();
if (context) {
g_main_context_invoke(context, /* callback */, this);
}
}
This expects GLib's GMainLoop to be running and pumping the default main context. However, flutter-pi uses libsystemd's sd-event for its event loop (as mentioned in the README: "libsystemd provides the event loop and dbus support for flutter-pi").
Since g_main_context_invoke() schedules work on a GLib main context that flutter-pi never iterates, the WebRTC callbacks are never executed. This causes:
- Initialization sequences to hang or fail silently
- Native resources to remain uninitialized
- Subsequent operations to fail with confusing errors
Comparison with flutter-elinux
The flutter_webrtc plugin works with flutter-elinux after thread marshalling fixes were implemented (see flutter-elinux-plugins#7). The flutter-elinux project appears to use GLib's main loop, which is why g_main_context_invoke() works there.
Possible Solutions
-
flutter-pi side: Add GLib main context integration alongside sd-event, or provide an API for plugins to schedule work on the main thread
-
flutter_webrtc side: Create an alternative task_runner implementation using sd-event for flutter-pi compatibility
-
Hybrid approach: flutter-pi could expose a platform-agnostic callback mechanism that plugins can use for thread marshalling
Related Issues/References
Summary
The
flutter_webrtcplugin does not work with flutter-pi due to a main loop incompatibility. The plugin's Linux implementation uses GLib'sg_main_context_invoke()for thread marshalling, but flutter-pi uses libsystemd's sd-event loop instead.Environment
Error Output
The random high ports (37130, 42876, etc.) suggest libwebrtc's internal networking fails during ICE candidate gathering because initialization callbacks never complete.
Root Cause Analysis
The
flutter_webrtcplugin's Linux implementation relies on GLib for thread marshalling intask_runner_linux.cc:This expects GLib's
GMainLoopto be running and pumping the default main context. However, flutter-pi uses libsystemd's sd-event for its event loop (as mentioned in the README: "libsystemd provides the event loop and dbus support for flutter-pi").Since
g_main_context_invoke()schedules work on a GLib main context that flutter-pi never iterates, the WebRTC callbacks are never executed. This causes:Comparison with flutter-elinux
The
flutter_webrtcplugin works with flutter-elinux after thread marshalling fixes were implemented (see flutter-elinux-plugins#7). The flutter-elinux project appears to use GLib's main loop, which is whyg_main_context_invoke()works there.Possible Solutions
flutter-pi side: Add GLib main context integration alongside sd-event, or provide an API for plugins to schedule work on the main thread
flutter_webrtc side: Create an alternative
task_runnerimplementation using sd-event for flutter-pi compatibilityHybrid approach: flutter-pi could expose a platform-agnostic callback mechanism that plugins can use for thread marshalling
Related Issues/References