Skip to content

Add support for flutter_webrtc plugin (GLib main context incompatibility) #509

Description

@iagormoraes

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:

  1. Initialization sequences to hang or fail silently
  2. Native resources to remain uninitialized
  3. 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

  1. flutter-pi side: Add GLib main context integration alongside sd-event, or provide an API for plugins to schedule work on the main thread

  2. flutter_webrtc side: Create an alternative task_runner implementation using sd-event for flutter-pi compatibility

  3. Hybrid approach: flutter-pi could expose a platform-agnostic callback mechanism that plugins can use for thread marshalling

Related Issues/References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions