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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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