8000 Merge branch 'master' of https://github.com/flutter-webrtc/flutter-we… · tmthecoder/flutter-webrtc@47b0134 · GitHub
[go: up one dir, main page]

Skip to content

Commit 47b0134

Browse files
committed
2 parents 41f533a + 9e84d6c commit 47b0134

13 files changed

+149
-56
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
# Changelog
22

33
--------------------------------------------
4+
[0.6.4] - 2021.05.02
5+
6+
* [Android] Fix getting screen capture on Huawei only successful in the first time. (#523)
7+
* [Android] Add configuration "cryptoOptions" in parseRTCConfiguration().
8+
* [Dart] Change getLocalDescription,getRemoteDescription,RTCRtpSenderWeb.track returns to nullable.
9+
* [Dart] Fixed bug in RTCPeerConnectionWeb.removeTrack.
10+
* [Dart] Change MediaStreamTrack.captureFrame returns to ByteBuffer to compatible with web API.
11+
* [Dart] Do null safety check in onRemoveStream,onRemoveTrack and MediaStream.getTrackById.
12+
* [Android] Add reStartCamera method when the camera is preempted by other apps.
13+
* [Web] Refactored RTCVideoRendererWeb and RTCVideoViewWeb, using video and audio HTML tags to render audio and video streams separately.
14+
415
[0.6.3] - 2021.04.03
516

617
* [Dart] Change RTCRtpSender.track to nullable.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Flutter-WebRTC
22

3-
[![Financial Contributors on Open Collective](https://opencollective.com/flutter-webrtc/all/badge.svg?label=financial+contributors)](https://opencollective.com/flutter-webrtc) [![pub package](https://img.shields.io/pub/v/flutter_webrtc.svg)](https://pub.dartlang.org/packages/flutter_webrtc) [![Gitter](https://badges.gitter.im/flutter-webrtc/Lobby.svg)](https://gitter.im/flutter-webrtc/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
3+
[![Financial Contributors on Open Collective](https://opencollective.com/flutter-webrtc/all/badge.svg?label=financial+contributors)](https://opencollective.com/flutter-webrtc) [![pub package](https://img.shields.io/pub/v/flutter_webrtc.svg)](https://pub.dartlang.org/packages/flutter_webrtc) [![Gitter](https://badges.gitter.im/flutter-webrtc/Lobby.svg)](https://gitter.im/flutter-webrtc/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![slack](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen)](https://join.slack.com/t/flutterwebrtc/shared_invite/zt-q83o7y1s-FExGLWEvtkPKM8ku_F8cEQ)
44

55
WebRTC plugin for Flutter Mobile/Desktop/Web
66

android/src/main/java/com/cloudwebrtc/webrtc/GetUserMediaImpl.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
import org.webrtc.MediaStream;
6161
import org.webrtc.MediaStreamTrack;
6262
import org.webrtc.PeerConnectionFactory;
63-
import org.webrtc.ScreenCapturerAndroid;
6463
import org.webrtc.SurfaceTextureHelper;
6564
import org.webrtc.VideoCapturer;
6665
import org.webrtc.VideoSource;
@@ -466,7 +465,7 @@ protected void onReceiveResult(int requestCode, Bundle resultData) {
466465
MediaStreamTrack[] tracks = new MediaStreamTrack[1];
467466
VideoCapturer videoCapturer = null;
468467
videoCapturer =
469-
new ScreenCapturerAndroid(
468+
new OrientationAwareScreenCapturer(
470469
mediaProjectionData,
471470
new MediaProjection.Callback() {
472471
@Override
@@ -502,7 +501,7 @@ public void onStop() {
502501
info.capturer = videoCapturer;
503502

504503
videoCapturer.startCapture(info.width, info.height, info.fps);
505-
Log.d(TAG, "ScreenCapturerAndroid.startCapture: " + info.width + "x" + info.height + "@" + info.fps);
504+
Log.d(TAG, "OrientationAwareScreenCapturer.startCapture: " + info.width + "x" + info.height + "@" + info.fps);
506505

507506
String trackId = stateProvider.getNextTrackUUID();
508507
mVideoCapturers.put(trackId, info);
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.cloudwebrtc.webrtc;
2+
3+
import org.webrtc.ScreenCapturerAndroid;
4+
import org.webrtc.SurfaceTextureHelper;
5+
import org.webrtc.CapturerObserver;
6+
import org.webrtc.VideoFrame;
7+
8+
import android.annotation.TargetApi;
9+
import android.content.Context;
10+
import android.content.Intent;
11+
import android.media.projection.MediaProjection;
12+
import android.util.Log;
13+
import android.view.Surface;
14+
import android.view.WindowManager;
15+
16+
17+
/**
18+
* An implementation of ScreenCapturerAndroid to capture the screen content while being aware of device orientation
19+
*/
20+
@TargetApi(21)
21+
public class OrientationAwareScreenCapturer
22+
extends ScreenCapturerAndroid {
23+
private Context applicationContext;
24+
private WindowManager windowManager;
25+
private int width;
26+
private int height;
27+
private boolean isPortrait;
28+
29+
/**
30+
* Constructs a new Screen Capturer.
31+
*
32+
* @param mediaProjectionPermissionResultData the result data of MediaProjection permission
33+
* activity; the calling app must validate that result code is Activity.RESULT_OK before
34+
* calling this method.
35+
* @param mediaProjectionCallback MediaProjection callback to implement application specific
36+
* logic in events such as when the user revokes a previously granted capture permission.
37+
**/
38+
public OrientationAwareScreenCapturer(Intent mediaProjectionPermissionResultData,
39+
MediaProjection.Callback mediaProjectionCallback) {
40+
super(mediaProjectionPermissionResultData, mediaProjectionCallback);
41+
}
42+
43+
@Override
44+
public synchronized void initialize(SurfaceTextureHelper surfaceTextureHelper, Context applicationContext, CapturerObserver capturerObserver) {
45+
super.initialize(surfaceTextureHelper, applicationContext, capturerObserver);
46+
this.applicationContext = applicationContext;
47+
Log.d("OrientationAwareSC", "OrientationAwareScreenCapturer: initialized and orientation isPortrait? " + this.isPortrait);
48+
}
49+
50+
@Override
51+
public synchronized void startCapture(int width, int height, int ignoredFramerate) {
52+
this.windowManager = (WindowManager) applicationContext.getSystemService(
53+
Context.WINDOW_SERVICE);
54+
this.isPortrait = isDeviceOrientationPortrait();
55+
if (this.isPortrait) {
56+
this.width = width;
57+
this.height = height;
58+
} else {
59+
this.height = width;
60+
this.width = height;
61+
}
62+
super.startCapture(width, height, ignoredFramerate);
63+
}
64+
65+
@Override
66+
public void onFrame(VideoFrame frame) {
67+
final boolean isOrientationPortrait = isDeviceOrientationPortrait();
68+
if (isOrientationPortrait != this.isPortrait) {
69+
this.isPortrait = isOrientationPortrait;
70+
71+
if (this.isPortrait) {
72+
super.changeCaptureFormat(this.width, this.height, 15);
73+
} else {
74+
super.changeCaptureFormat(this.height, this.width, 15);
75+
}
76+
}
77+
super.onFrame(frame);
78+
}
79+
80+
private boolean isDeviceOrientationPortrait() {
81+
final int surfaceRotation = windowManager.getDefaultDisplay().getRotation();
82+
83+
return surfaceRotation != Surface.ROTATION_90 && surfaceRotation != Surface.ROTATION_270;
84+
}
85+
86+
}

common/darwin/Classes/FlutterWebRTCPlugin.m

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,8 +1142,8 @@ - (nonnull RTCConfiguration *)RTCConfiguration:(id)json
11421142
}
11431143

11441144
// candidateNetworkPolicy (private api)
1145-
if (json[@"candidateNetworkPolicy" != nil &&
1146-
[json[@"candidateNetworkPolicy"] isKindOfClass:[NSString class]]]) {
1145+
if (json[@"candidateNetworkPolicy"] != nil &&
1146+
[json[@"candidateNetworkPolicy"] isKindOfClass:[NSString class]]) {
11471147
NSString* candidateNetworkPolicy = json[@"candidateNetworkPolicy"];
11481148
if ([candidateNetworkPolicy isEqualToString:@"all"]) {
11491149
config.candidateNetworkPolicy = RTCCandidateNetworkPolicyAll;
@@ -1153,7 +1153,7 @@ - (nonnull RTCConfiguration *)RTCConfiguration:(id)json
11531153
}
11541154

11551155
// KeyType (private api)
1156-
if (json[@"keyType" != nil && [json[@"keyType"] isKindOfClass:[NSString class]]]) {
1156+
if (json[@"keyType"] != nil && [json[@"keyType"] isKindOfClass:[NSString class]]) {
11571157
NSString* keyType = json[@"keyType"];
11581158
if ([keyType isEqualToString:@"RSA"]) {
11591159
config.keyType = RTCEncryptionKeyTypeRSA;
@@ -1163,8 +1163,8 @@ - (nonnull RTCConfiguration *)RTCConfiguration:(id)json
11631163
}
11641164

11651165
// continualGatheringPolicy (private api)
1166-
if (json[@"continualGatheringPolicy" != nil &&
1167-
[json[@"continualGatheringPolicy"] isKindOfClass:[NSString class]]]) {
1166+
if (json[@"continualGatheringPolicy"] != nil &&
1167+
[json[@"continualGatheringPolicy"] isKindOfClass:[NSString class]]) {
11681168
NSString* continualGatheringPolicy = json[@"continualGatheringPolicy"];
11691169
if ([continualGatheringPolicy isEqualToString:@"gather_once"]) {
11701170
config.continualGatheringPolicy = RTCContinualGatheringPolicyGatherOnce;
@@ -1174,49 +1174,49 @@ - (nonnull RTCConfiguration *)RTCConfiguration:(id)json
11741174
}
11751175

11761176
// audioJitterBufferMaxPackets (private api)
1177-
if (json[@"audioJitterBufferMaxPackets" != nil &&
1178-
[json[@"audioJitterBufferMaxPackets"] isKindOfClass:[NSNumber class]]]) {
1177+
if (json[@"audioJitterBufferMaxPackets"] != nil &&
1178+
[json[@"audioJitterBufferMaxPackets"] isKindOfClass:[NSNumber class]]) {
11791179
NSNumber* audioJitterBufferMaxPackets = json[@"audioJitterBufferMaxPackets"];
11801180
config.audioJitterBufferMaxPackets = [audioJitterBufferMaxPackets intValue];
11811181
}
11821182

11831183
// iceConnectionReceivingTimeout (private api)
1184-
if (json[@"iceConnectionReceivingTimeout" != nil &&
1185-
[json[@"iceConnectionReceivingTimeout"] isKindOfClass:[NSNumber class]]]) {
1184+
if (json[@"iceConnectionReceivingTimeout"] != nil &&
1185+
[json[@"iceConnectionReceivingTimeout"] isKindOfClass:[NSNumber class]]) {
11861186
NSNumber* iceConnectionReceivingTimeout = json[@"iceConnectionReceivingTimeout"];
11871187
config.iceConnectionReceivingTimeout = [iceConnectionReceivingTimeout intValue];
11881188
}
11891189

11901190
// iceBackupCandidatePairPingInterval (private api)
1191-
if (json[@"iceBackupCandidatePairPingInterval" != nil &&
1192-
[json[@"iceBackupCandidatePairPingInterval"] isKindOfClass:[NSNumber class]]]) {
1191+
if (json[@"iceBackupCandidatePairPingInterval"] != nil &&
1192+
[json[@"iceBackupCandidatePairPingInterval"] isKindOfClass:[NSNumber class]]) {
11931193
NSNumber* iceBackupCandidatePairPingInterval = json[@"iceConnectionReceivingTimeout"];
11941194
config.iceBackupCandidatePairPingInterval = [iceBackupCandidatePairPingInterval intValue];
11951195
}
11961196

11971197
// audioJitterBufferFastAccelerate (private api)
1198-
if (json[@"audioJitterBufferFastAccelerate" != nil &&
1199-
[json[@"audioJitterBufferFastAccelerate"] isKindOfClass:[NSNumber class]]]) {
1198+
if (json[@"audioJitterBufferFastAccelerate"] != nil &&
1199+
[json[@"audioJitterBufferFastAccelerate"] isKindOfClass:[NSNumber class]]) {
12001200
NSNumber* audioJitterBufferFastAccelerate = json[@"audioJitterBufferFastAccelerate"];
12011201
config.audioJitterBufferFastAccelerate = [audioJitterBufferFastAccelerate boolValue];
12021202
}
12031203

12041204
// pruneTurnPorts (private api)
1205-
if (json[@"pruneTurnPorts" != nil && [json[@"pruneTurnPorts"] isKindOfClass:[NSNumber class]]]) {
1206-
NSNumber* pruneTurnPorts = json[@"audioJitterBufferFastAccelerate"];
1205+
if (json[@"pruneTurnPorts"] != nil && [json[@"pruneTurnPorts"] isKindOfClass:[NSNumber class]]) {
1206+
NSNumber* pruneTurnPorts = json[@"pruneTurnPorts"];
12071207
config.shouldPruneTurnPorts = [pruneTurnPorts boolValue];
12081208
}
12091209

12101210
// presumeWritableWhenFullyRelayed (private api)
1211-
if (json[@"presumeWritableWhenFullyRelayed" != nil &&
1212-
[json[@"presumeWritableWhenFullyRelayed"] isKindOfClass:[NSNumber class]]]) {
1211+
if (json[@"presumeWritableWhenFullyRelayed"] != nil &&
1212+
[json[@"presumeWritableWhenFullyRelayed"] isKindOfClass:[NSNumber class]]) {
12131213
NSNumber* presumeWritableWhenFullyRelayed = json[@"presumeWritableWhenFullyRelayed"];
12141214
config.shouldPresumeWritableWhenFullyRelayed = [presumeWritableWhenFullyRelayed boolValue];
12151215
}
12161216

12171217
// cryptoOptions (private api)
1218-
if (json[@"cryptoOptions" != nil &&
1219-
[json[@"cryptoOptions"] isKindOfClass:[NSDictionary class]]]) {
1218+
if (json[@"cryptoOptions"] != nil &&
1219+
[json[@"cryptoOptions"] isKindOfClass:[NSDictionary class]]) {
12201220
id options = json[@"cryptoOptions"];
12211221
BOOL srtpEnableGcmCryptoSuites = NO;
12221222
BOOL sframeRequireFrameEncryption = NO;
@@ -1229,20 +1229,20 @@ - (nonnull RTCConfiguration *)RTCConfiguration:(id)json
12291229
srtpEnableGcmCryptoSuites = [value boolValue];
12301230
}
12311231

1232-
if (options[@"requireFrameEncryption" != nil &&
1233-
[options[@"requireFrameEncryption"] isKindOfClass:[NSNumber class]]]) {
1232+
if (options[@"requireFrameEncryption"] != nil &&
1233+
[options[@"requireFrameEncryption"] isKindOfClass:[NSNumber class]]) {
12341234
NSNumber* value = options[@"requireFrameEncryption"];
12351235
sframeRequireFrameEncryption = [value boolValue];
12361236
}
12371237

1238-
if (options[@"enableEncryptedRtpHeaderExtensions" != nil &&
1239-
[options[@"enableEncryptedRtpHeaderExtensions"] isKindOfClass:[NSNumber class]]]) {
1238+
if (options[@"enableEncryptedRtpHeaderExtensions"] != nil &&
1239+
[options[@"enableEncryptedRtpHeaderExtensions"] isKindOfClass:[NSNumber class]]) {
12401240
NSNumber* value = options[@"enableEncryptedRtpHeaderExtensions"];
12411241
srtpEnableEncryptedRtpHeaderExtensions = [value boolValue];
12421242
}
12431243

1244-
if (options[@"enableAes128Sha1_32CryptoCipher" != nil &&
1245-
[options[@"enableAes128Sha1_32CryptoCipher"] isKindOfClass:[NSNumber class]]]) {
1244+
if (options[@"enableAes128Sha1_32CryptoCipher"] != nil &&
1245+
[options[@"enableAes128Sha1_32CryptoCipher"] isKindOfClass:[NSNumber class]]) {
12461246
NSNumber* value = options[@"enableAes128Sha1_32CryptoCipher"];
12471247
srtpEnableAes128Sha1_32CryptoCipher = [value boolValue];
12481248
}

example/lib/src/get_user_media_sample.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,9 @@ class _GetUserMediaSampleState extends State<GetUserMediaSample> {
156156
content:
157157
Image.memory(frame.asUint8List(), height: 720, width: 1280),
158158
actions: <Widget>[
159-
FlatButton(
160-
child: Text('OK'),
159+
TextButton(
161160
onPressed: Navigator.of(context, rootNavigator: true).pop,
161+
child: Text('OK'),
162162
)
163163
],
164164
));

lib/src/native/media_stream_track_impl.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,9 @@ class MediaStreamTrackNative extends MediaStreamTrack {
8585
'path': filePath.path + '/captureFrame.png'
8686
},
8787
);
88-
return File(filePath.path + '/captureFrame.png').readAsBytes().then((
89-
value) => value.buffer);
88+
return File(filePath.path + '/captureFrame.png')
89+
.readAsBytes()
90+
.then((value) => value.buffer);
9091
}
9192

9293
@override

lib/src/native/rtc_peerconnection_impl.dart

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ class RTCPeerConnectionNative extends RTCPeerConnection {
6969

7070
Future<RTCSessionDescription?> get localDescription => getLocalDescription();
7171

72-
Future<RTCSessionDescription?> get remoteDescription => getRemoteDescription();
72+
Future<RTCSessionDescription?> get remoteDescription =>
73+
getRemoteDescription();
7374

7475
/*
7576
* PeerConnection event listener.
@@ -116,8 +117,8 @@ class RTCPeerConnectionNative extends RTCPeerConnection {
116117
case 'onRemoveStream':
117118
String streamId = map['streamId'];
118119

119-
for(var item in _remoteStreams){
120-
if(item.id == streamId){
120+
for (var item in _remoteStreams) {
121+
if (item.id == streamId) {
121122
onRemoveStream?.call(item);
122123
break;
123124
}
@@ -153,11 +154,11 @@ class RTCPeerConnectionNative extends RTCPeerConnection {
153154
break;
154155
case 'onRemoveTrack':
155156
String streamId = map['streamId'];
156-
for(var item in _remoteStreams){
157-
if(item.id == streamId){
157+
for (var item in _remoteStreams) {
158+
if (item.id == streamId) {
158159
Map<dynamic, dynamic> track = map['track'];
159-
var oldTrack = MediaStreamTrackNative(
160-
map['trackId'], track['label'], track['kind'], track['enabled']);
160+
var oldTrack = MediaStreamTrackNative(map['trackId'],
161+
track['label'], track['kind'], track['enabled']);
161162
onRemoveTrack?.call(item, oldTrack);
162163
break;
163164
}

lib/src/native/rtc_rtp_transceiver_impl.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ class RTCRtpTransceiverNative extends RTCRtpTransceiver {
6767
factory RTCRtpTransceiverNative.fromMap(Map<dynamic, dynamic> map,
6868
{required String peerConnectionId}) {
6969
var transceiver = RTCRtpTransceiverNative(
70-
map['transceiverId'],
70+
map['transceiverId'] ?? '',
7171
typeStringToRtpTransceiverDirection[map['direction']]!,
72-
map['mid'],
72+
map['mid'] ?? '',
7373
RTCRtpSenderNative.fromMap(map['sender'],
7474
peerConnectionId: peerConnectionId),
7575
RTCRtpReceiverNative.fromMap(map['receiver'],

lib/src/native/utils.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class WebRTC {
2424
static bool get platformIsWeb => false;
2525

2626
static Future<T> invokeMethod<T, P>(String methodName,
27-
[dynamic? param]) async {
27+
[dynamic param]) async {
2828
var response = await _channel.invokeMethod<T>(
2929
methodName,
3030
param,

lib/src/web/media_stream_track_impl.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ class MediaStreamTrackWeb extends MediaStreamTrack {
6969
canvas.getContext('bitmaprenderer') as html.ImageBitmapRenderingContext;
7070
renderer.transferFromImageBitmap(bitmap);
7171
final blod = await canvas.toBlob();
72-
var array = await js.promiseToFuture(js.callMethod(blod, 'arrayBuffer', []));
72+
var array =
73+
await js.promiseToFuture(js.callMethod(blod, 'arrayBuffer', []));
7374
bitmap.close();
7475
return array;
7576
}

lib/src/web/rtc_video_renderer_impl.dart

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ const String _kDefaultErrorMessage =
3333
'No further diagnostic information can be determined or provided.';
3434

3535
class RTCVideoRendererWeb extends VideoRenderer {
36-
html.AudioElement? _audioElement;
37-
3836
RTCVideoRendererWeb() : _textureId = _textureCounter++;
3937

38+
html.AudioElement? _audioElement;
39+
4040
static int _textureCounter = 1;
4141

4242
html.MediaStream? _videoStream;
@@ -47,7 +47,7 @@ class RTCVideoRendererWeb extends VideoRen 10000 derer {
4747

4848
final int _textureId;
4949

50-
bool _mirror = false;
50+
bool mirror = false;
5151

5252
final _subscriptions = <StreamSubscription>[];
5353

@@ -56,13 +56,7 @@ class RTCVideoRendererWeb extends VideoRenderer {
5656
bool _muted = false;
5757

5858
set objectFit(String fit) =>
59-
findHtmlView()?.style?.objectFit = _objectFit = fit;
60-
61-
bool get mirror => _mirror;
62-
63-
set mirror(bool mirror) {
64-
_mirror = mirror;
65-
}
59+
findHtmlView()?.style.objectFit = _objectFit = fit;
6660

6761
@override
6862
int get videoWidth => value.width.toInt();
@@ -212,7 +206,7 @@ class RTCVideoRendererWeb extends VideoRenderer {
212206
..style.objectFit = _objectFit
213207
..style.border = 'none'
214208
..srcObject = _videoStream
215-
..id = "video_$id"
209+
..id = 'video_$id'
216210
..setAttribute('playsinline', 'true');
217211

218212
_subscriptions.add(

0 commit comments

Comments
 (0)
0