feat: add getBufferedAmount for DataChannel. (#1796)

* feat: add getBufferedAmount for DataChannel.

* update.

* update.

* fix.

* update binary for linux.
This commit is contained in:
CloudWebRTC
2025-03-24 15:14:59 +08:00
committed by GitHub
parent 1c2ff6f497
commit 82176788a7
16 changed files with 118 additions and 11 deletions

View File

@ -482,6 +482,12 @@ public class MethodCallHandlerImpl implements MethodCallHandler, StateProvider {
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");
@ -2039,6 +2045,17 @@ public class MethodCallHandlerImpl implements MethodCallHandler, StateProvider {
}
}
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.

View File

@ -168,6 +168,18 @@ class PeerConnectionObserver implements PeerConnection.Observer, EventChannel.St
}
}
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) {

View File

@ -40,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>);

View File

@ -87,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,

View File

@ -352,6 +352,29 @@ void FlutterWebRTC::HandleMethodCall(
return;
}
DataChannelSend(data_channel, type, data, std::move(result));
} else if (method_call.method_name().compare("dataChannelGetBufferedAmount") == 0) {
if (!method_call.arguments()) {
result->Error("Bad Arguments", "Null constraints arguments received");
return;
}
const EncodableMap params =
GetValue<EncodableMap>(*method_call.arguments());
const std::string peerConnectionId = findString(params, "peerConnectionId");
RTCPeerConnection* pc = PeerConnectionForId(peerConnectionId);
if (pc == nullptr) {
result->Error("dataChannelGetBufferedAmountFailed",
"dataChannelGetBufferedAmount() peerConnection is null");
return;
}
const std::string dataChannelId = findString(params, "dataChannelId");
RTCDataChannel* data_channel = DataChannelForId(dataChannelId);
if (data_channel == nullptr) {
result->Error("dataChannelGetBufferedAmountFailed",
"dataChannelGetBufferedAmount() data_channel is null");
return;
}
DataChannelGetBufferedAmount(data_channel, std::move(result));
} else if (method_call.method_name().compare("dataChannelClose") == 0) {
if (!method_call.arguments()) {
result->Error("Bad Arguments", "Null constraints arguments received");

View File

@ -24,4 +24,7 @@
data:(nonnull NSString*)data
type:(nonnull NSString*)type;
- (void)dataChannelGetBufferedAmount:(nonnull NSString*)peerConnectionId
dataChannelId:(nonnull NSString*)dataChannelId
result:(nonnull FlutterResult)result;
@end

View File

@ -118,6 +118,18 @@
}
}
- (void)dataChannelGetBufferedAmount:(nonnull NSString*)peerConnectionId
dataChannelId:(nonnull NSString*)dataChannelId
result:(nonnull FlutterResult)result {
RTCPeerConnection* peerConnection = self.peerConnections[peerConnectionId];
RTCDataChannel* dataChannel = peerConnection.dataChannels[dataChannelId];
if(dataChannel == NULL || dataChannel.readyState != RTCDataChannelStateOpen) {
result(@{@"bufferedAmount": @(-1)});
} else {
result(@{@"bufferedAmount": @(dataChannel.bufferedAmount)});
}
}
- (void)dataChannelSend:(nonnull NSString*)peerConnectionId
dataChannelId:(nonnull NSString*)dataChannelId
data:(id)data

View File

@ -570,7 +570,14 @@ bypassVoiceProcessing:(BOOL)bypassVoiceProcessing {
[self dataChannelSend:peerConnectionId dataChannelId:dataChannelId data:data type:type];
result(nil);
} else if ([@"dataChannelClose" isEqualToString:call.method]) {
} else if ([@"dataChannelGetBufferedAmount" isEqualToString:call.method]) {
NSDictionary* argsMap = call.arguments;
NSString* peerConnectionId = argsMap[@"peerConnectionId"];
NSString* dataChannelId = argsMap[@"dataChannelId"];
[self dataChannelGetBufferedAmount:peerConnectionId dataChannelId:dataChannelId result:result];
}
else if ([@"dataChannelClose" isEqualToString:call.method]) {
NSDictionary* argsMap = call.arguments;
NSString* peerConnectionId = argsMap[@"peerConnectionId"];
NSString* dataChannelId = argsMap[@"dataChannelId"];

View File

@ -49,12 +49,14 @@ class _DataChannelLoopBackSampleState extends State<DataChannelLoopBackSample> {
_dataChannel2Status += '\ndataChannel2: state: ${state.toString()}';
});
};
_dataChannel2!.onMessage = (data) {
_dataChannel2!.onMessage = (data) async {
var bufferedAmount = await _dataChannel2!.getBufferedAmount();
setState(() {
_dataChannel2Status +=
'\ndataChannel2: Received message: ${data.text}';
'\ndataChannel2: Received message: ${data.text}, bufferedAmount: $bufferedAmount';
});
_dataChannel2!.send(RTCDataChannelMessage(
await _dataChannel2!.send(RTCDataChannelMessage(
'(dataChannel2 ==> dataChannel1) Hello from dataChannel2 echo !!!'));
};
};
@ -69,10 +71,12 @@ class _DataChannelLoopBackSampleState extends State<DataChannelLoopBackSample> {
}
};
_dataChannel1!.onMessage = (data) => setState(() {
_dataChannel1Status +=
'\ndataChannel1: Received message: ${data.text}';
});
_dataChannel1!.onMessage = (data) async {
var bufferedAmount = await _dataChannel2!.getBufferedAmount();
_dataChannel1Status +=
'\ndataChannel1: Received message: ${data.text}, bufferedAmount: $bufferedAmount';
setState(() {});
};
var offer = await _peerConnection1!.createOffer({});
print('peerConnection1 offer: ${offer.sdp}');

View File

@ -109,6 +109,17 @@ class RTCDataChannelNative extends RTCDataChannel {
}
}
@override
Future<int> getBufferedAmount() async {
final Map<dynamic, dynamic> response = await WebRTC.invokeMethod(
'dataChannelGetBufferedAmount', <String, dynamic>{
'peerConnectionId': _peerConnectionId,
'dataChannelId': _flutterId
});
_bufferedAmount = response['bufferedAmount'];
return _bufferedAmount;
}
@override
Future<void> send(RTCDataChannelMessage message) async {
await WebRTC.invokeMethod('dataChannelSend', <String, dynamic>{

View File

@ -8,12 +8,12 @@ environment:
dependencies:
collection: ^1.17.0
dart_webrtc: ^1.5.2+hotfix.1
dart_webrtc: ^1.5.3
flutter:
sdk: flutter
path_provider: ^2.0.2
web: ^1.0.0
webrtc_interface: ^1.2.1+hotfix.1
webrtc_interface: ^1.2.2+hotfix.1
dev_dependencies:
flutter_test:

View File

@ -103,6 +103,13 @@ class RTCDataChannel : public RefCountInterface {
*/
virtual int id() const = 0;
/**
* Returns the amount of data buffered in the data channel.
*
* @return uint64_t
*/
virtual uint64_t buffered_amount() const = 0;
/**
* Returns the state of the data channel.
*/

View File

@ -21,7 +21,8 @@
#include "rtc_base/ref_count.h"
namespace libwebrtc {
class IceTransport : public rtc::RefCountInterface {
class IceTransport : public RefCountInterface {
public:
virtual IceTransport* internal() = 0;
};

Binary file not shown.

Binary file not shown.