@byteplus/react-native-rtc 1.1.1-rc.3 → 1.1.1-rc.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +5 -5
- package/android/proguard-rules.pro +1 -1
- package/android/src/live/java/com/volcengine/reactnative/vertc/live/VertcLive.java +77 -8
- package/ios/core/VertcHelper.h +9 -3
- package/ios/core/VertcHelper.m +67 -1
- package/ios/live/VertcLive.m +164 -8
- package/package.json +1 -1
- package/react-native-rtc.podspec +2 -2
package/android/build.gradle
CHANGED
|
@@ -83,7 +83,7 @@ android {
|
|
|
83
83
|
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
84
84
|
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
85
85
|
|
|
86
|
-
consumerProguardFiles 'proguard-rules.pro'
|
|
86
|
+
consumerProguardFiles 'proguard-rules.pro'
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
buildTypes {
|
|
@@ -108,15 +108,15 @@ if (enableUnionForRTCWithLive) {
|
|
|
108
108
|
android.sourceSets.main.java.srcDirs += 'src/live/java'
|
|
109
109
|
dependencies {
|
|
110
110
|
implementation project(':byteplus_react-native-live-push')
|
|
111
|
-
implementation "com.bytedanceapi:ttsdk-player_$license_type:1.46.300.
|
|
111
|
+
implementation "com.bytedanceapi:ttsdk-player_$license_type:1.46.300.3-test1"
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
if (enableUnionForRTCWithVod) {
|
|
116
116
|
android.sourceSets.main.java.srcDirs += 'src/vod/java'
|
|
117
|
-
//
|
|
117
|
+
//
|
|
118
118
|
// Might cause rtc api some error, just alpha version.
|
|
119
|
-
//
|
|
119
|
+
//
|
|
120
120
|
apiVolcEngineVersion = '1.5.0'
|
|
121
121
|
dependencies {
|
|
122
122
|
implementation "com.bytedanceapi:ttsdk-player_$license_type:1.46.300.2"
|
|
@@ -133,4 +133,4 @@ dependencies {
|
|
|
133
133
|
|
|
134
134
|
// Use the RTC SDK dependency determined by getNativeDep() which can be overridden by customer's app build.gradle.
|
|
135
135
|
implementation isBp ? "com.byteplus:BytePlusRTC:$rtcVersionToUse" : "com.volcengine:VolcEngineRTC:$rtcVersionToUse"
|
|
136
|
-
}
|
|
136
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Add project specific ProGuard rules here.
|
|
1
|
+
# Add project specific ProGuard rules here.
|
|
2
2
|
# By default, the flags in this file are appended to flags specified
|
|
3
3
|
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
|
4
4
|
# You can edit the include path and order by changing the proguardFiles
|
|
@@ -5,6 +5,7 @@ package com.volcengine.reactnative.vertc.live;
|
|
|
5
5
|
|
|
6
6
|
import android.util.Log;
|
|
7
7
|
|
|
8
|
+
import com.pandora.common.applog.AppLogWrapper;
|
|
8
9
|
import com.ss.avframework.live.VeLivePusherDef;
|
|
9
10
|
import com.ss.avframework.live.VeLiveVideoFrame;
|
|
10
11
|
import com.ss.avframework.opengl.RendererCommon;
|
|
@@ -18,6 +19,10 @@ import com.ss.bytertc.engine.data.VideoSourceType;
|
|
|
18
19
|
import java.util.concurrent.TimeUnit;
|
|
19
20
|
import com.ss.bytertc.engine.video.builder.GLTextureVideoFrameBuilder;
|
|
20
21
|
import com.volcengine.velive.rn.push.VeLivePushHelper;
|
|
22
|
+
import com.ss.avframework.live.filter.video.effect.CVEffectManager;
|
|
23
|
+
|
|
24
|
+
import org.json.JSONException;
|
|
25
|
+
import org.json.JSONObject;
|
|
21
26
|
|
|
22
27
|
import javax.annotation.Nonnull;
|
|
23
28
|
|
|
@@ -29,6 +34,30 @@ public class VertcLive {
|
|
|
29
34
|
private org.json.JSONObject mOptions;
|
|
30
35
|
private RTCVideo mEngine;
|
|
31
36
|
|
|
37
|
+
// 新增:VeLivePusherStatistics转字符串辅助方法
|
|
38
|
+
private String statisticsToString(VeLivePusherDef.VeLivePusherStatistics stats) {
|
|
39
|
+
if (stats == null) return "null";
|
|
40
|
+
return new StringBuilder()
|
|
41
|
+
.append("VeLivePusherStatistics{")
|
|
42
|
+
.append("url='").append(stats.url).append('\'')
|
|
43
|
+
.append(", encodeWidth=").append(stats.encodeWidth)
|
|
44
|
+
.append(", encodeHeight=").append(stats.encodeHeight)
|
|
45
|
+
.append(", captureWidth=").append(stats.captureWidth)
|
|
46
|
+
.append(", captureHeight=").append(stats.captureHeight)
|
|
47
|
+
.append(", captureFps=").append(stats.captureFps)
|
|
48
|
+
.append(", encodeFps=").append(stats.encodeFps)
|
|
49
|
+
.append(", transportFps=").append(stats.transportFps)
|
|
50
|
+
.append(", fps=").append(stats.fps)
|
|
51
|
+
.append(", videoBitrate=").append(stats.videoBitrate)
|
|
52
|
+
.append(", minVideoBitrate=").append(stats.minVideoBitrate)
|
|
53
|
+
.append(", maxVideoBitrate=").append(stats.maxVideoBitrate)
|
|
54
|
+
.append(", encodeVideoBitrate=").append(stats.encodeVideoBitrate)
|
|
55
|
+
.append(", transportVideoBitrate=").append(stats.transportVideoBitrate)
|
|
56
|
+
.append(", encodeAudioBitrate=").append(stats.encodeAudioBitrate)
|
|
57
|
+
.append(", codec=").append(stats.codec)
|
|
58
|
+
.append('}').toString();
|
|
59
|
+
}
|
|
60
|
+
|
|
32
61
|
/**
|
|
33
62
|
* @brief Start to capture live stream.
|
|
34
63
|
*/
|
|
@@ -43,7 +72,30 @@ public class VertcLive {
|
|
|
43
72
|
if (mLivePusher == null) {
|
|
44
73
|
throw new RuntimeException("[Unknown LivePusher] can't find pusher instance by view id.");
|
|
45
74
|
}
|
|
46
|
-
|
|
75
|
+
|
|
76
|
+
mLivePusher.setStatisticsObserver(new VeLivePusherDef.VeLivePusherStatisticsObserver() {
|
|
77
|
+
@Override
|
|
78
|
+
public void onStatistics(VeLivePusherDef.VeLivePusherStatistics statistics) {
|
|
79
|
+
String staticLog = statisticsToString(statistics);
|
|
80
|
+
JSONObject json = new JSONObject();
|
|
81
|
+
try {
|
|
82
|
+
JSONObject jsonObject = new JSONObject();
|
|
83
|
+
jsonObject.put("staticLog",staticLog);
|
|
84
|
+
json.put("event_key", "livcore_statistics").put("message", jsonObject.toString()).put("effectcost", CVEffectManager.cvCostdurationMs+"ms");
|
|
85
|
+
Log.d("flexttv>>>>> ", json.toString());
|
|
86
|
+
} catch (JSONException e) {
|
|
87
|
+
throw new RuntimeException(e);
|
|
88
|
+
}
|
|
89
|
+
AppLogWrapper.onEventV3("live_client_monitor_log",json);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@Override
|
|
93
|
+
public void onLogMonitor(JSONObject logInfo) {
|
|
94
|
+
VeLivePusherDef.VeLivePusherStatisticsObserver.super.onLogMonitor(logInfo);
|
|
95
|
+
}
|
|
96
|
+
}, 2);
|
|
97
|
+
|
|
98
|
+
|
|
47
99
|
// set video source as external
|
|
48
100
|
engine.setVideoSourceType(getStreamIndex(), VideoSourceType.VIDEO_SOURCE_TYPE_EXTERNAL);
|
|
49
101
|
// set video frame listener
|
|
@@ -53,12 +105,29 @@ public class VertcLive {
|
|
|
53
105
|
public VeLivePusherDef.VeLiveVideoFrameSource getObservedVideoFrameSource() {
|
|
54
106
|
return new VeLivePusherDef.VeLiveVideoFrameSource(VeLivePusherDef.VeLiveVideoFrameSource.VeLiveVideoFrameSourcePreEncode);
|
|
55
107
|
}
|
|
56
|
-
|
|
108
|
+
private static final long INTERVAL_MS = 1000; // 计算间隔为1秒
|
|
109
|
+
private long lastTime = 0;
|
|
110
|
+
private int frameCount = 0;
|
|
57
111
|
@Override
|
|
58
112
|
public void onPreEncodeVideoFrame(VeLiveVideoFrame frame) {
|
|
59
113
|
int ret_status = -1;
|
|
60
114
|
StreamIndex streamIndex = getStreamIndex();
|
|
61
115
|
|
|
116
|
+
long currentTime = System.currentTimeMillis();
|
|
117
|
+
frameCount++;
|
|
118
|
+
|
|
119
|
+
if (lastTime == 0) {
|
|
120
|
+
lastTime = currentTime;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (currentTime - lastTime >= INTERVAL_MS) {
|
|
124
|
+
int fps = frameCount;
|
|
125
|
+
Log.d("flexttv>>>>> FrameRateCalculator", "当前帧率: " + fps + " FPS");
|
|
126
|
+
frameCount = 0;
|
|
127
|
+
lastTime = currentTime;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
62
131
|
float[] mMVPMatrix = RendererCommon.convertMatrixFromAndroidGraphicsMatrix(frame.getTextureMatrix());
|
|
63
132
|
GLTextureVideoFrameBuilder builder = new GLTextureVideoFrameBuilder(
|
|
64
133
|
frame.isOesTextureFrame() ? VideoPixelFormat.TEXTURE_OES : VideoPixelFormat.TEXTURE_2D
|
|
@@ -70,7 +139,7 @@ public class VertcLive {
|
|
|
70
139
|
.setTextureMatrix(mMVPMatrix)
|
|
71
140
|
.setEGLContext(VeLivePusher.getEGLContext())
|
|
72
141
|
.setTimeStampUs(System.currentTimeMillis() * TimeUnit.MILLISECONDS.toNanos(1));
|
|
73
|
-
|
|
142
|
+
|
|
74
143
|
if (streamIndex == StreamIndex.STREAM_INDEX_MAIN) {
|
|
75
144
|
ret_status = engine.pushExternalVideoFrame(builder.build());
|
|
76
145
|
}
|
|
@@ -85,7 +154,7 @@ public class VertcLive {
|
|
|
85
154
|
}
|
|
86
155
|
};
|
|
87
156
|
mLivePusher.addVideoFrameListener(mListener);
|
|
88
|
-
|
|
157
|
+
|
|
89
158
|
return 0;
|
|
90
159
|
} catch (Exception err) {
|
|
91
160
|
Log.d(TAG, "startLiveVideoCapture failed:" + err.getMessage());
|
|
@@ -122,17 +191,17 @@ public class VertcLive {
|
|
|
122
191
|
}
|
|
123
192
|
}
|
|
124
193
|
|
|
125
|
-
|
|
194
|
+
|
|
126
195
|
// Get VeLivePusher from Object
|
|
127
196
|
private VeLivePusher getVeLivePusher(String pusherViewId) {
|
|
128
|
-
|
|
197
|
+
|
|
129
198
|
if (VeLivePushHelper.getPusher(pusherViewId) != null) {
|
|
130
199
|
return VeLivePushHelper.getPusher(pusherViewId);
|
|
131
200
|
}
|
|
132
|
-
|
|
201
|
+
|
|
133
202
|
return null;
|
|
134
203
|
}
|
|
135
|
-
|
|
204
|
+
|
|
136
205
|
// Get StreamIndex from options
|
|
137
206
|
private StreamIndex getStreamIndex() {
|
|
138
207
|
Number index = mOptions.optInt("streamIndex", StreamIndex.STREAM_INDEX_MAIN.value());
|
package/ios/core/VertcHelper.h
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#import "RTCHeader.h"
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
11
11
|
@interface VertcHelper : NSObject
|
|
12
12
|
|
|
13
13
|
+ (instancetype) getInstance;
|
|
@@ -19,5 +19,11 @@
|
|
|
19
19
|
error:(NSInteger)errorCode;
|
|
20
20
|
|
|
21
21
|
- (int) invokeStartPushSingleStreamToCDN:(ByteRTCVideo *)rtc taskId:(NSString *_Nonnull)taskID singleStream:(ByteRTCPushSingleStreamParam *_Nonnull)singleStream;
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
- (void)schedualTimerWithIdentifier:(NSString *)name
|
|
23
|
+
interval:(NSTimeInterval)interval
|
|
24
|
+
queue:(dispatch_queue_t)queue
|
|
25
|
+
repeats:(BOOL)repeats
|
|
26
|
+
action:(dispatch_block_t)action;
|
|
27
|
+
- (void)cancelTimerWithName:(NSString *)name;
|
|
28
|
+
@end
|
|
29
|
+
NS_ASSUME_NONNULL_END
|
package/ios/core/VertcHelper.m
CHANGED
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
#import "RTCHeader.h"
|
|
10
10
|
#import <VertcHelper.h>
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
@interface VertcHelper ()
|
|
13
|
+
@property (nonatomic, strong) NSMutableDictionary *timerList;
|
|
14
|
+
@property (nonatomic, strong) NSRecursiveLock *lock;
|
|
15
|
+
@end
|
|
13
16
|
#pragma mark - Helper
|
|
14
17
|
@implementation VertcHelper
|
|
15
18
|
|
|
@@ -22,6 +25,14 @@
|
|
|
22
25
|
return instance;
|
|
23
26
|
}
|
|
24
27
|
|
|
28
|
+
- (instancetype)init {
|
|
29
|
+
if (self = [super init]) {
|
|
30
|
+
self.timerList = [NSMutableDictionary dictionary];
|
|
31
|
+
self.lock = [[NSRecursiveLock alloc] init];
|
|
32
|
+
}
|
|
33
|
+
return self;
|
|
34
|
+
}
|
|
35
|
+
|
|
25
36
|
+ (bool)isUnionLiveModeEnable {
|
|
26
37
|
#ifdef ENABLE_UNION_FOR_RTC_WITH_LIVE
|
|
27
38
|
return true;
|
|
@@ -46,4 +57,59 @@
|
|
|
46
57
|
return res;
|
|
47
58
|
}
|
|
48
59
|
|
|
60
|
+
- (void)schedualTimerWithIdentifier:(NSString *)name
|
|
61
|
+
interval:(NSTimeInterval)interval
|
|
62
|
+
queue:(dispatch_queue_t)queue
|
|
63
|
+
repeats:(BOOL)repeats
|
|
64
|
+
action:(dispatch_block_t)action {
|
|
65
|
+
if (!name || name.length == 0 || !action) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
[_lock lock];
|
|
69
|
+
if (!queue) {
|
|
70
|
+
queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
dispatch_source_t timer = [self.timerList objectForKey:name];
|
|
74
|
+
if (!timer) {
|
|
75
|
+
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
|
|
76
|
+
dispatch_resume(timer);
|
|
77
|
+
[self.timerList setValue:timer forKey:name];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), interval * NSEC_PER_SEC, 0.01 * NSEC_PER_SEC);
|
|
81
|
+
__weak __typeof(self)weakSelf = self;
|
|
82
|
+
dispatch_source_set_event_handler(timer, ^{
|
|
83
|
+
action();
|
|
84
|
+
__strong __typeof(weakSelf)self = weakSelf;
|
|
85
|
+
if (!repeats) {
|
|
86
|
+
[self cancelTimerWithName:name];
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
[_lock unlock];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
- (void)cancelTimerWithName:(NSString *)name {
|
|
93
|
+
[_lock lock];
|
|
94
|
+
if (name == nil) {
|
|
95
|
+
[_lock unlock];
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
dispatch_source_t timer = [self.timerList objectForKey:name];
|
|
99
|
+
if (timer) {
|
|
100
|
+
[self.timerList removeObjectForKey:name];
|
|
101
|
+
dispatch_source_cancel(timer);
|
|
102
|
+
}
|
|
103
|
+
[_lock unlock];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (void)cancelAllTimers {
|
|
107
|
+
[_lock lock];
|
|
108
|
+
for (dispatch_source_t timer in self.timerList) {
|
|
109
|
+
dispatch_source_cancel(timer);
|
|
110
|
+
}
|
|
111
|
+
[self.timerList removeAllObjects];
|
|
112
|
+
[_lock unlock];
|
|
113
|
+
}
|
|
49
114
|
@end
|
|
115
|
+
|
package/ios/live/VertcLive.m
CHANGED
|
@@ -6,16 +6,24 @@
|
|
|
6
6
|
#import <TTSDKFramework/TTSDKFramework.h>
|
|
7
7
|
#import <TTSDKFramework/VeLivePusherDef.h>
|
|
8
8
|
#import "VeLivePushHelper.h"
|
|
9
|
+
#import "VertcHelper.h"
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
@interface VeLiveFpsTracker : NSObject
|
|
12
|
+
- (void)start;
|
|
13
|
+
- (void)stop;
|
|
14
|
+
- (void)updateCaptureVieoWidth:(int)width height:(int)height;
|
|
15
|
+
- (void)updatePreEncodeVieoWidth:(int)width height:(int)height;
|
|
16
|
+
- (void)updateCaptureFrame:(NSInteger)frameCount;
|
|
17
|
+
- (void)updatePreEncodeFrame:(NSInteger)frameCount;
|
|
18
|
+
- (void)updateAfterRTCFrame:(NSInteger)frameCount;
|
|
19
|
+
@end
|
|
11
20
|
|
|
12
21
|
@interface VertcLive ()
|
|
13
|
-
|
|
14
22
|
@property (nonatomic, strong) NSDictionary *options;
|
|
15
23
|
@property (nonatomic, strong) ByteRTCVideo *rtcEngine;
|
|
16
24
|
@property (nonatomic, strong) VeLivePusher *livePusher;
|
|
17
25
|
@property (nonatomic, strong) id<VeLiveVideoFrameListener> videoFrameListener;
|
|
18
|
-
|
|
26
|
+
@property (nonatomic, strong) VeLiveFpsTracker *fpsTracker;
|
|
19
27
|
@end
|
|
20
28
|
|
|
21
29
|
@implementation VertcLive
|
|
@@ -27,6 +35,8 @@
|
|
|
27
35
|
self.livePusher = nil;
|
|
28
36
|
self.rtcEngine = nil;
|
|
29
37
|
self.options = nil;
|
|
38
|
+
[self.fpsTracker stop];
|
|
39
|
+
self.fpsTracker = nil;
|
|
30
40
|
}
|
|
31
41
|
|
|
32
42
|
- (int)startLiveVideoCapture:(ByteRTCVideo *)rtc viewId:(NSString *)viewId options:(NSDictionary *)options {
|
|
@@ -35,6 +45,11 @@
|
|
|
35
45
|
if (pusher == nil) {
|
|
36
46
|
@throw [NSException exceptionWithName:@"unknown videoEngine" reason:@"can't get pusher" userInfo:@{}];
|
|
37
47
|
}
|
|
48
|
+
if (self.fpsTracker != nil) {
|
|
49
|
+
[self.fpsTracker stop];
|
|
50
|
+
} else {
|
|
51
|
+
self.fpsTracker = [[VeLiveFpsTracker alloc] init];
|
|
52
|
+
}
|
|
38
53
|
self.rtcEngine = rtc;
|
|
39
54
|
self.options = options;
|
|
40
55
|
self.livePusher = pusher;
|
|
@@ -42,15 +57,16 @@
|
|
|
42
57
|
NSInteger streamIndexValue = [options[@"streamIndex"] integerValue] ?: 0;
|
|
43
58
|
ByteRTCStreamIndex streamIndex = (streamIndexValue == 1) ? ByteRTCStreamIndexScreen : ByteRTCStreamIndexMain;
|
|
44
59
|
[rtc setVideoSourceType:ByteRTCVideoSourceTypeExternal WithStreamIndex:streamIndex];
|
|
45
|
-
|
|
60
|
+
|
|
61
|
+
[self.fpsTracker start];
|
|
46
62
|
int addRes = [self.livePusher addVideoFrameListener:self];
|
|
47
63
|
NSLog(@"addVideoFrameListener result: %d", addRes);
|
|
48
|
-
|
|
49
64
|
return 0;
|
|
50
65
|
}
|
|
51
66
|
|
|
52
67
|
- (int)stopLiveVideoCapture {
|
|
53
68
|
if (self.rtcEngine == nil || self.livePusher == nil) {
|
|
69
|
+
[self.fpsTracker stop];
|
|
54
70
|
return 0;
|
|
55
71
|
}
|
|
56
72
|
if (self.livePusher && self.videoFrameListener) {
|
|
@@ -66,11 +82,12 @@
|
|
|
66
82
|
self.options = nil;
|
|
67
83
|
self.rtcEngine = nil;
|
|
68
84
|
self.livePusher = nil;
|
|
85
|
+
[self.fpsTracker stop];
|
|
69
86
|
return 0;
|
|
70
87
|
}
|
|
71
88
|
|
|
72
89
|
- (VeLiveVideoFrameSource)getObservedVideoFrameSource {
|
|
73
|
-
return VeLiveVideoFrameSourcePreEncode;
|
|
90
|
+
return VeLiveVideoFrameSourceCapture | VeLiveVideoFrameSourcePreEncode;
|
|
74
91
|
}
|
|
75
92
|
|
|
76
93
|
- (ByteRTCVideoPixelFormat)convertToRtcPixelFormat:(VeLivePixelFormat)format {
|
|
@@ -85,11 +102,16 @@
|
|
|
85
102
|
return ByteRTCVideoPixelFormatUnknown;
|
|
86
103
|
}
|
|
87
104
|
|
|
105
|
+
- (void)onCaptureVideoFrame:(VeLiveVideoFrame *)frame {
|
|
106
|
+
[self.fpsTracker updateCaptureFrame:1];
|
|
107
|
+
[self.fpsTracker updateCaptureVieoWidth:frame.width height:frame.height];
|
|
108
|
+
}
|
|
109
|
+
|
|
88
110
|
- (void)onPreEncodeVideoFrame:(VeLiveVideoFrame *)frame {
|
|
89
|
-
|
|
111
|
+
[self.fpsTracker updatePreEncodeFrame:1];
|
|
112
|
+
[self.fpsTracker updatePreEncodeVieoWidth:frame.width height:frame.height];
|
|
90
113
|
NSInteger streamIndexValue = [self.options[@"streamIndex"] integerValue] ?: 0;
|
|
91
114
|
ByteRTCStreamIndex streamIndex = (streamIndexValue == 1) ? ByteRTCStreamIndexScreen : ByteRTCStreamIndexMain;
|
|
92
|
-
|
|
93
115
|
int res = 0;
|
|
94
116
|
if (streamIndex == ByteRTCStreamIndexMain) {
|
|
95
117
|
ByteRTCVideoPixelFormat pixelFormat = [self convertToRtcPixelFormat:frame.pixelFormat];
|
|
@@ -112,9 +134,12 @@
|
|
|
112
134
|
}
|
|
113
135
|
|
|
114
136
|
res = [self.rtcEngine pushExternalVideoFrame: videoFrame];
|
|
137
|
+
|
|
138
|
+
[self.fpsTracker updateAfterRTCFrame:1];
|
|
115
139
|
}
|
|
116
140
|
if (streamIndex == ByteRTCStreamIndexScreen) {
|
|
117
141
|
res = [self.rtcEngine pushScreenVideoFrame:frame.pixelBuffer time:frame.pts rotation:frame.rotation];
|
|
142
|
+
[self.fpsTracker updateAfterRTCFrame:1];
|
|
118
143
|
}
|
|
119
144
|
if (res != 0 && res != -202) {
|
|
120
145
|
NSLog(@"bytertc push video frame fail return '%d'", res);
|
|
@@ -122,3 +147,134 @@
|
|
|
122
147
|
}
|
|
123
148
|
|
|
124
149
|
@end
|
|
150
|
+
|
|
151
|
+
@protocol VeLiveTrackerProtocol <NSObject>
|
|
152
|
+
+ (void)sendPusherEventWith:(NSString *)eventKey api:(nullable NSString *)api value:(nullable id)value result:(nullable id)result;
|
|
153
|
+
@end
|
|
154
|
+
|
|
155
|
+
@interface VeLiveFpsTracker ()
|
|
156
|
+
@property (nonatomic, strong) Class <VeLiveTrackerProtocol> trackerCls;
|
|
157
|
+
@property (nonatomic, assign) NSTimeInterval lastTimestamp;
|
|
158
|
+
@property (nonatomic, assign) NSInteger captureFrameCount;
|
|
159
|
+
@property (nonatomic, assign) NSInteger preEncodeFrameCount;
|
|
160
|
+
@property (nonatomic, assign) NSInteger afterRtcFrameCount;
|
|
161
|
+
@property (nonatomic, strong) dispatch_queue_t queue;
|
|
162
|
+
@property (nonatomic, copy) NSString *timerName;
|
|
163
|
+
@property (nonatomic, assign) CGSize captureSize;
|
|
164
|
+
@property (nonatomic, assign) CGSize preEncodeSize;
|
|
165
|
+
@end
|
|
166
|
+
|
|
167
|
+
@implementation VeLiveFpsTracker
|
|
168
|
+
- (instancetype)init {
|
|
169
|
+
if (self = [super init]) {
|
|
170
|
+
_timerName = @"VeLiveFpsTracker";
|
|
171
|
+
_trackerCls = NSClassFromString(@"VeLiveTracker");
|
|
172
|
+
_queue = dispatch_queue_create("VeLiveFpsTracker-Queue", DISPATCH_QUEUE_SERIAL);
|
|
173
|
+
}
|
|
174
|
+
return self;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
- (void)start {
|
|
178
|
+
[self clearFrameRecordAsync:NSDate.date.timeIntervalSince1970 * 1000];
|
|
179
|
+
__weak __typeof(self)weakSelf = self;
|
|
180
|
+
[[VertcHelper getInstance] schedualTimerWithIdentifier:self.timerName
|
|
181
|
+
interval:2
|
|
182
|
+
queue:self.queue
|
|
183
|
+
repeats:YES
|
|
184
|
+
action:^{
|
|
185
|
+
__strong __typeof(weakSelf)self = weakSelf;
|
|
186
|
+
[self reportIfNeed];
|
|
187
|
+
}];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
- (void)stop {
|
|
191
|
+
[[VertcHelper getInstance] cancelTimerWithName:_timerName];
|
|
192
|
+
[self clearFrameRecordAsync:0];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
- (void)clearFrameRecordAsync:(NSTimeInterval)timestamp {
|
|
196
|
+
__weak __typeof(self)weakSelf = self;
|
|
197
|
+
dispatch_async(self.queue, ^{
|
|
198
|
+
__strong __typeof(weakSelf)self = weakSelf;
|
|
199
|
+
[self clearFrameRecord:timestamp];
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
- (void)clearFrameRecord:(NSTimeInterval)timestamp {
|
|
204
|
+
self.lastTimestamp = timestamp;
|
|
205
|
+
self.captureFrameCount = 0;
|
|
206
|
+
self.preEncodeFrameCount = 0;
|
|
207
|
+
self.afterRtcFrameCount = 0;
|
|
208
|
+
self.captureSize = CGSizeZero;
|
|
209
|
+
self.preEncodeSize = CGSizeZero;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
- (void)updateCaptureFrame:(NSInteger)frameCount {
|
|
213
|
+
__weak __typeof(self)weakSelf = self;
|
|
214
|
+
dispatch_async(self.queue, ^{
|
|
215
|
+
__strong __typeof(weakSelf)self = weakSelf;
|
|
216
|
+
self.captureFrameCount += frameCount;
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
- (void)updatePreEncodeFrame:(NSInteger)frameCount {
|
|
221
|
+
__weak __typeof(self)weakSelf = self;
|
|
222
|
+
dispatch_async(self.queue, ^{
|
|
223
|
+
__strong __typeof(weakSelf)self = weakSelf;
|
|
224
|
+
self.preEncodeFrameCount += frameCount;
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
- (void)updateAfterRTCFrame:(NSInteger)frameCount {
|
|
229
|
+
__weak __typeof(self)weakSelf = self;
|
|
230
|
+
dispatch_async(self.queue, ^{
|
|
231
|
+
__strong __typeof(weakSelf)self = weakSelf;
|
|
232
|
+
self.afterRtcFrameCount += frameCount;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
- (void)updateCaptureVieoWidth:(int)width height:(int)height {
|
|
237
|
+
__weak __typeof(self)weakSelf = self;
|
|
238
|
+
dispatch_async(self.queue, ^{
|
|
239
|
+
__strong __typeof(weakSelf)self = weakSelf;
|
|
240
|
+
self.captureSize = CGSizeMake((CGFloat)width, (CGFloat)height);
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
- (void)updatePreEncodeVieoWidth:(int)width height:(int)height {
|
|
245
|
+
__weak __typeof(self)weakSelf = self;
|
|
246
|
+
dispatch_async(self.queue, ^{
|
|
247
|
+
__strong __typeof(weakSelf)self = weakSelf;
|
|
248
|
+
self.preEncodeSize = CGSizeMake((CGFloat)width, (CGFloat)height);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
- (void)reportIfNeed {
|
|
253
|
+
NSTimeInterval currentTime = NSDate.date.timeIntervalSince1970 * 1000;
|
|
254
|
+
NSTimeInterval duration = MAX(1, currentTime - self.lastTimestamp);
|
|
255
|
+
|
|
256
|
+
int captureFps = (int)((self.captureFrameCount * 1000.0) / duration);
|
|
257
|
+
int preEncodeFps = (int)((self.preEncodeFrameCount * 1000.0) / duration);
|
|
258
|
+
int afterRtcFps = (int)((self.afterRtcFrameCount * 1000.0) / duration);
|
|
259
|
+
|
|
260
|
+
[self reportEvent:@"livcore_statistics_fps" value:@{
|
|
261
|
+
@"captureFps" : @(captureFps),
|
|
262
|
+
@"preEncodeFps" : @(preEncodeFps),
|
|
263
|
+
@"afterRtcFps" : @(afterRtcFps),
|
|
264
|
+
@"captureSize" : NSStringFromCGSize(self.captureSize),
|
|
265
|
+
@"preEncodeSize" : NSStringFromCGSize(self.preEncodeSize),
|
|
266
|
+
}];
|
|
267
|
+
[self clearFrameRecord:currentTime];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
- (void)reportEvent:(NSString *)key value:(NSDictionary *)value {
|
|
271
|
+
if (self.trackerCls != nil
|
|
272
|
+
&& [self.trackerCls respondsToSelector:@selector(sendPusherEventWith:api:value:result:)]) {
|
|
273
|
+
[self.trackerCls sendPusherEventWith:key api:@"" value:value result:@""];
|
|
274
|
+
}
|
|
275
|
+
#if DEBUG
|
|
276
|
+
NSLog(@"report: %@ %@", key, value);
|
|
277
|
+
#endif
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
@end
|
package/package.json
CHANGED
package/react-native-rtc.podspec
CHANGED
|
@@ -33,8 +33,8 @@ Pod::Spec.new do |s|
|
|
|
33
33
|
'ENABLE_UNION_FOR_RTC_WITH_LIVE' => '$(ENABLE_UNION_FOR_RTC_WITH_LIVE)',
|
|
34
34
|
'ENABLE_UNION_FOR_RTC_WITH_VOD' => '$(ENABLE_UNION_FOR_RTC_WITH_VOD)',
|
|
35
35
|
'UNION_FOR_RTC_WITH_LIVE_VERSION' => '$(UNION_FOR_RTC_WITH_LIVE_VERSION)',
|
|
36
|
-
'UNION_FOR_RTC_WITH_VOD_VERSION' => '$(UNION_FOR_RTC_WITH_VOD_VERSION)'
|
|
37
|
-
'VOLC_API_ENGINE_VERSION_FOR_RTC' => '$(VOLC_API_ENGINE_VERSION_FOR_RTC)'
|
|
36
|
+
'UNION_FOR_RTC_WITH_VOD_VERSION' => '$(UNION_FOR_RTC_WITH_VOD_VERSION)',
|
|
37
|
+
'VOLC_API_ENGINE_VERSION_FOR_RTC' => '$(VOLC_API_ENGINE_VERSION_FOR_RTC)'
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
s.default_subspec = 'Core'
|