Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@

# Changelog

[1.0.0] - 2025-03-31
* Bumped StreamWebRTC version to 125.6422.065
* Synced flutter-webrtc v0.13.0
* [All] feat: add getBufferedAmount for DataChannel.
* [Windows] fix: fixed non-platform thread call error.

[1.0.0-dev.1] - 2025-03-14
* Switched native webrtc dependencies for iOS and Android to Stream's internal builds
* Replaced deprecated `onSurfaceDestroyed` with `onSurfaceCleanup` in `SurfaceTextureRenderer`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,12 @@ public void onMethodCall(MethodCall call, @NonNull Result notSafeResult) {
createDataChannel(peerConnectionId, label, new ConstraintsMap(dataChannelDict), result);
break;
}
case "dataChannelGetBufferedAmount": {
String peerConnectionId = call.argument("peerConnectionId");
String dataChannelId = call.argument("dataChannelId");
dataChannelGetBufferedAmount(peerConnectionId, dataChannelId, result);
break;
}
case "dataChannelSend": {
String peerConnectionId = call.argument("peerConnectionId");
String dataChannelId = call.argument("dataChannelId");
Expand Down Expand Up @@ -2062,6 +2068,17 @@ public void dataChannelSend(String peerConnectionId, String dataChannelId, ByteB
}
}

public void dataChannelGetBufferedAmount(String peerConnectionId, String dataChannelId, Result result) {
PeerConnectionObserver pco
= mPeerConnectionObservers.get(peerConnectionId);
if (pco == null || pco.getPeerConnection() == null) {
Log.d(TAG, "dataChannelGetBufferedAmount() peerConnection is null");
resultError("dataChannelGetBufferedAmount", "peerConnection is null", result);
} else {
pco.dataChannelGetBufferedAmount(dataChannelId, result);
}
}

public void dataChannelClose(String peerConnectionId, String dataChannelId) {
// Forward to PeerConnectionObserver which deals with DataChannels
// because DataChannel is owned by PeerConnection.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,18 @@ void dataChannelSend(String dataChannelId, ByteBuffer byteBuffer, Boolean isBina
}
}

void dataChannelGetBufferedAmount(String dataChannelId, Result result) {
DataChannel dataChannel = dataChannels.get(dataChannelId);
if (dataChannel != null) {
ConstraintsMap params = new ConstraintsMap();
params.putLong("bufferedAmount", dataChannel.bufferedAmount());
result.success(params.toMap());
} else {
Log.d(TAG, "dataChannelGetBufferedAmount() dataChannel is null");
resultError("dataChannelGetBufferedAmount", "DataChannel is null", result);
}
}

RtpTransceiver getRtpTransceiverById(String id) {
RtpTransceiver transceiver = transceivers.get(id);
if (null == transceiver) {
Expand Down
10 changes: 8 additions & 2 deletions common/cpp/include/flutter_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@

#include <list>
#include <memory>
#include <string>
#include <mutex>
#include <optional>
#include <queue>
#include <string>

typedef flutter::EncodableValue EncodableValue;
typedef flutter::EncodableMap EncodableMap;
Expand All @@ -27,6 +29,8 @@ typedef flutter::EventSink<EncodableValue> EventSink;
typedef flutter::MethodCall<EncodableValue> MethodCall;
typedef flutter::MethodResult<EncodableValue> MethodResult;

class TaskRunner;

// foo.StringValue() becomes std::get<std::string>(foo)
// foo.IsString() becomes std::holds_alternative<std::string>(foo)

Expand Down Expand Up @@ -90,7 +94,8 @@ inline double findDouble(const EncodableMap& map, const std::string& key) {
return 0.0;
}

inline std::optional<double> maybeFindDouble(const EncodableMap& map, const std::string& key) {
inline std::optional<double> maybeFindDouble(const EncodableMap& map,
const std::string& key) {
auto it = map.find(EncodableValue(key));
if (it != map.end() && TypeIs<double>(it->second))
return GetValue<double>(it->second);
Expand Down Expand Up @@ -171,6 +176,7 @@ class EventChannelProxy {
public:
static std::unique_ptr<EventChannelProxy> Create(
BinaryMessenger* messenger,
TaskRunner* task_runner,
const std::string& channelName);

virtual ~EventChannelProxy() = default;
Expand Down
4 changes: 4 additions & 0 deletions common/cpp/include/flutter_data_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class FlutterRTCDataChannelObserver : public RTCDataChannelObserver {
public:
FlutterRTCDataChannelObserver(scoped_refptr<RTCDataChannel> data_channel,
BinaryMessenger* messenger,
TaskRunner* task_runner,
const std::string& channel_name);
virtual ~FlutterRTCDataChannelObserver();

Expand Down Expand Up @@ -39,6 +40,9 @@ class FlutterDataChannel {
const EncodableValue& data,
std::unique_ptr<MethodResultProxy>);

void DataChannelGetBufferedAmount(RTCDataChannel* data_channel,
std::unique_ptr<MethodResultProxy> result);

void DataChannelClose(RTCDataChannel* data_channel,
const std::string& data_channel_uuid,
std::unique_ptr<MethodResultProxy>);
Expand Down
4 changes: 2 additions & 2 deletions common/cpp/include/flutter_frame_cryptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ namespace stream_webrtc_flutter_plugin {

class FlutterFrameCryptorObserver : public libwebrtc::RTCFrameCryptorObserver {
public:
FlutterFrameCryptorObserver(BinaryMessenger* messenger,const std::string& channelName)
: event_channel_(EventChannelProxy::Create(messenger, channelName)) {}
FlutterFrameCryptorObserver(BinaryMessenger* messenger, TaskRunner* task_runner, const std::string& channelName)
: event_channel_(EventChannelProxy::Create(messenger, task_runner, channelName)) {}
void OnFrameCryptionStateChanged(
const string participant_id,
libwebrtc::RTCFrameCryptionState state);
Expand Down
1 change: 1 addition & 0 deletions common/cpp/include/flutter_peerconnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class FlutterPeerConnectionObserver : public RTCPeerConnectionObserver {
FlutterPeerConnectionObserver(FlutterWebRTCBase* base,
scoped_refptr<RTCPeerConnection> peerconnection,
BinaryMessenger* messenger,
TaskRunner* task_runner,
const std::string& channel_name,
std::string& peerConnectionId);

Expand Down
1 change: 1 addition & 0 deletions common/cpp/include/flutter_video_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class FlutterVideoRenderer

void initialize(TextureRegistrar* registrar,
BinaryMessenger* messenger,
TaskRunner* task_runner,
std::unique_ptr<flutter::TextureVariant> texture,
int64_t texture_id);

Expand Down
2 changes: 2 additions & 0 deletions common/cpp/include/flutter_webrtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class FlutterWebRTCPlugin : public flutter::Plugin {
virtual BinaryMessenger* messenger() = 0;

virtual TextureRegistrar* textures() = 0;

virtual TaskRunner* task_runner() = 0;
};

class FlutterWebRTC : public FlutterWebRTCBase,
Expand Down
3 changes: 2 additions & 1 deletion common/cpp/include/flutter_webrtc_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class FlutterWebRTCBase {
enum ParseConstraintType { kMandatory, kOptional };

public:
FlutterWebRTCBase(BinaryMessenger* messenger, TextureRegistrar* textures);
FlutterWebRTCBase(BinaryMessenger* messenger, TextureRegistrar* textures, TaskRunner* task_runner);
~FlutterWebRTCBase();

std::string GenerateUUID();
Expand Down Expand Up @@ -122,6 +122,7 @@ class FlutterWebRTCBase {

protected:
BinaryMessenger* messenger_;
TaskRunner *task_runner_;
TextureRegistrar* textures_;
std::unique_ptr<EventChannelProxy> event_channel_;
};
Expand Down
17 changes: 17 additions & 0 deletions common/cpp/include/task_runner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2024 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PACKAGES_FLUTTER_WEBRTC_TASK_RUNNER_H_
#define PACKAGES_FLUTTER_WEBRTC_TASK_RUNNER_H_

#include <functional>

using TaskClosure = std::function<void()>;

class TaskRunner {
public:
virtual void EnqueueTask(TaskClosure task) = 0;
virtual ~TaskRunner() = default;
};

#endif // PACKAGES_FLUTTER_WEBRTC_TASK_RUNNER_H_
118 changes: 70 additions & 48 deletions common/cpp/src/flutter_common.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#include "flutter_common.h"
#include "task_runner.h"

#include <memory>

class MethodCallProxyImpl : public MethodCallProxy {
public:
Expand Down Expand Up @@ -66,56 +69,75 @@ std::unique_ptr<MethodResultProxy> MethodResultProxy::Create(
}

class EventChannelProxyImpl : public EventChannelProxy {
public:
EventChannelProxyImpl(BinaryMessenger* messenger,
const std::string& channelName)
: channel_(std::make_unique<EventChannel>(
messenger,
channelName,
&flutter::StandardMethodCodec::GetInstance())) {
auto handler = std::make_unique<
flutter::StreamHandlerFunctions<EncodableValue>>(
[&](const EncodableValue* arguments,
std::unique_ptr<flutter::EventSink<EncodableValue>>&& events)
-> std::unique_ptr<flutter::StreamHandlerError<EncodableValue>> {
sink_ = std::move(events);
for (auto& event : event_queue_) {
sink_->Success(event);
}
event_queue_.clear();
on_listen_called_ = true;
return nullptr;
},
[&](const EncodableValue* arguments)
-> std::unique_ptr<flutter::StreamHandlerError<EncodableValue>> {
on_listen_called_ = false;
return nullptr;
});

channel_->SetStreamHandler(std::move(handler));
}

virtual ~EventChannelProxyImpl() {}

void Success(const EncodableValue& event, bool cache_event = true) override {
if (on_listen_called_) {
public:
EventChannelProxyImpl(BinaryMessenger* messenger,
TaskRunner* task_runner,
const std::string& channelName)
: channel_(std::make_unique<EventChannel>(
messenger,
channelName,
&flutter::StandardMethodCodec::GetInstance())),
task_runner_(task_runner) {
auto handler = std::make_unique<
flutter::StreamHandlerFunctions<EncodableValue>>(
[&](const EncodableValue* arguments,
std::unique_ptr<flutter::EventSink<EncodableValue>>&& events)
-> std::unique_ptr<flutter::StreamHandlerError<EncodableValue>> {
sink_ = std::move(events);
std::weak_ptr<EventSink> weak_sink = sink_;
for (auto& event : event_queue_) {
PostEvent(event);
}
event_queue_.clear();
on_listen_called_ = true;
return nullptr;
},
[&](const EncodableValue* arguments)
-> std::unique_ptr<flutter::StreamHandlerError<EncodableValue>> {
on_listen_called_ = false;
return nullptr;
});

channel_->SetStreamHandler(std::move(handler));
}

virtual ~EventChannelProxyImpl() {}

void Success(const EncodableValue& event, bool cache_event = true) override {
if (on_listen_called_) {
PostEvent(event);
} else {
if (cache_event) {
event_queue_.push_back(event);
}
}
}

void PostEvent(const EncodableValue& event) {
if(task_runner_) {
std::weak_ptr<EventSink> weak_sink = sink_;
task_runner_->EnqueueTask([weak_sink, event]() {
auto sink = weak_sink.lock();
if (sink) {
sink->Success(event);
}
});
} else {
sink_->Success(event);
} else {
if (cache_event) {
event_queue_.push_back(event);
}
}
}

private:
std::unique_ptr<EventChannel> channel_;
std::unique_ptr<EventSink> sink_;
std::list<EncodableValue> event_queue_;
bool on_listen_called_ = false;
};
}
}

private:
std::unique_ptr<EventChannel> channel_;
std::shared_ptr<flutter::EventSink<flutter::EncodableValue>> sink_;
std::list<EncodableValue> event_queue_;
bool on_listen_called_ = false;
TaskRunner* task_runner_;
};

std::unique_ptr<EventChannelProxy> EventChannelProxy::Create(
BinaryMessenger* messenger,
TaskRunner* task_runner,
const std::string& channelName) {
return std::make_unique<EventChannelProxyImpl>(messenger, channelName);
}
return std::make_unique<EventChannelProxyImpl>(messenger, task_runner, channelName);
}
12 changes: 10 additions & 2 deletions common/cpp/src/flutter_data_channel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ namespace stream_webrtc_flutter_plugin {
FlutterRTCDataChannelObserver::FlutterRTCDataChannelObserver(
scoped_refptr<RTCDataChannel> data_channel,
BinaryMessenger* messenger,
TaskRunner* task_runner,
const std::string& channelName)
: event_channel_(EventChannelProxy::Create(messenger, channelName)),
: event_channel_(EventChannelProxy::Create(messenger, task_runner, channelName)),
data_channel_(data_channel) {
data_channel_->RegisterObserver(this);
}
Expand Down Expand Up @@ -53,7 +54,7 @@ void FlutterDataChannel::CreateDataChannel(
"FlutterWebRTC/dataChannelEvent" + peerConnectionId + uuid;

std::unique_ptr<FlutterRTCDataChannelObserver> observer(
new FlutterRTCDataChannelObserver(data_channel, base_->messenger_,
new FlutterRTCDataChannelObserver(data_channel, base_->messenger_, base_->task_runner_,
event_channel));

base_->lock();
Expand Down Expand Up @@ -86,6 +87,13 @@ void FlutterDataChannel::DataChannelSend(
result->Success();
}

void FlutterDataChannel::DataChannelGetBufferedAmount(RTCDataChannel* data_channel,
std::unique_ptr<MethodResultProxy> result) {
EncodableMap params;
params[EncodableValue("bufferedAmount")] = EncodableValue((int64_t)data_channel->buffered_amount());
result->Success(EncodableValue(params));
}

void FlutterDataChannel::DataChannelClose(
RTCDataChannel* data_channel,
const std::string& data_channel_uuid,
Expand Down
4 changes: 2 additions & 2 deletions common/cpp/src/flutter_frame_cryptor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ void FlutterFrameCryptor::FrameCryptorFactoryCreateFrameCryptor(
keyProvider);
std::string event_channel = "FlutterWebRTC/frameCryptorEvent" + uuid;

scoped_refptr<FlutterFrameCryptorObserver> observer(new RefCountedObject<FlutterFrameCryptorObserver>(base_->messenger_, event_channel));
scoped_refptr<FlutterFrameCryptorObserver> observer(new RefCountedObject<FlutterFrameCryptorObserver>(base_->messenger_, base_->task_runner_, event_channel));

frameCryptor->RegisterRTCFrameCryptorObserver(observer);

Expand All @@ -192,7 +192,7 @@ void FlutterFrameCryptor::FrameCryptorFactoryCreateFrameCryptor(

std::string event_channel = "FlutterWebRTC/frameCryptorEvent" + uuid;

scoped_refptr<FlutterFrameCryptorObserver> observer(new RefCountedObject<FlutterFrameCryptorObserver>(base_->messenger_, event_channel));
scoped_refptr<FlutterFrameCryptorObserver> observer(new RefCountedObject<FlutterFrameCryptorObserver>(base_->messenger_, base_->task_runner_, event_channel));

frameCryptor->RegisterRTCFrameCryptorObserver(observer.get());

Expand Down
Loading