@byteplus/react-native-live-push 1.1.3-rc.3 → 1.2.0-rc.0
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 +2 -2
- package/android/src/main/java/com/volcengine/velive/rn/push/ClassHelper.java +9 -0
- package/android/src/main/java/com/volcengine/velive/rn/push/NativeVariableManager.java +5 -8
- package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushModule.java +1 -0
- package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerManager.java +157 -144
- package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerView.java +33 -22
- package/ios/VeLiveMixerHelper.h +7 -5
- package/ios/VeLiveMixerHelper.m +32 -3
- package/ios/VeLiveMixerView.m +120 -112
- package/ios/VeLiveMixerViewManager.m +2 -2
- package/lib/commonjs/index.js +25072 -23532
- package/lib/commonjs/typescript/android/index.d.ts +0 -3
- package/lib/commonjs/typescript/codegen/android/api.d.ts +190 -644
- package/lib/commonjs/typescript/codegen/android/callback.d.ts +234 -2
- package/lib/commonjs/typescript/codegen/android/errorcode.d.ts +66 -0
- package/lib/commonjs/typescript/codegen/android/keytype.d.ts +1014 -181
- package/lib/commonjs/typescript/codegen/ios/api.d.ts +890 -0
- package/lib/commonjs/typescript/codegen/ios/callback.d.ts +162 -0
- package/lib/commonjs/typescript/codegen/ios/errorcode.d.ts +101 -1
- package/lib/commonjs/typescript/codegen/ios/keytype.d.ts +694 -0
- package/lib/commonjs/typescript/codegen/pack/api.d.ts +303 -686
- package/lib/commonjs/typescript/codegen/pack/callback.d.ts +37 -38
- package/lib/commonjs/typescript/codegen/pack/errorcode.d.ts +75 -5
- package/lib/commonjs/typescript/codegen/pack/keytype.d.ts +1002 -298
- package/lib/commonjs/typescript/core/api.d.ts +2 -1
- package/lib/commonjs/typescript/core/keytype.d.ts +1 -0
- package/lib/commonjs/typescript/core/pusher.d.ts +0 -3
- package/lib/module/index.js +25074 -23533
- package/lib/module/typescript/android/index.d.ts +0 -3
- package/lib/module/typescript/codegen/android/api.d.ts +190 -644
- package/lib/module/typescript/codegen/android/callback.d.ts +234 -2
- package/lib/module/typescript/codegen/android/errorcode.d.ts +66 -0
- package/lib/module/typescript/codegen/android/keytype.d.ts +1014 -181
- package/lib/module/typescript/codegen/ios/api.d.ts +890 -0
- package/lib/module/typescript/codegen/ios/callback.d.ts +162 -0
- package/lib/module/typescript/codegen/ios/errorcode.d.ts +101 -1
- package/lib/module/typescript/codegen/ios/keytype.d.ts +694 -0
- package/lib/module/typescript/codegen/pack/api.d.ts +303 -686
- package/lib/module/typescript/codegen/pack/callback.d.ts +37 -38
- package/lib/module/typescript/codegen/pack/errorcode.d.ts +75 -5
- package/lib/module/typescript/codegen/pack/keytype.d.ts +1002 -298
- package/lib/module/typescript/core/api.d.ts +2 -1
- package/lib/module/typescript/core/keytype.d.ts +1 -0
- package/lib/module/typescript/core/pusher.d.ts +0 -3
- package/lib/typescript/android/index.d.ts +0 -3
- package/lib/typescript/codegen/android/api.d.ts +190 -644
- package/lib/typescript/codegen/android/callback.d.ts +234 -2
- package/lib/typescript/codegen/android/errorcode.d.ts +66 -0
- package/lib/typescript/codegen/android/keytype.d.ts +1014 -181
- package/lib/typescript/codegen/ios/api.d.ts +890 -0
- package/lib/typescript/codegen/ios/callback.d.ts +162 -0
- package/lib/typescript/codegen/ios/errorcode.d.ts +101 -1
- package/lib/typescript/codegen/ios/keytype.d.ts +694 -0
- package/lib/typescript/codegen/pack/api.d.ts +303 -686
- package/lib/typescript/codegen/pack/callback.d.ts +37 -38
- package/lib/typescript/codegen/pack/errorcode.d.ts +75 -5
- package/lib/typescript/codegen/pack/keytype.d.ts +1002 -298
- package/lib/typescript/core/api.d.ts +2 -1
- package/lib/typescript/core/keytype.d.ts +1 -0
- package/lib/typescript/core/pusher.d.ts +0 -3
- package/package.json +1 -1
- package/react-native-velive-push.podspec +3 -3
- package/android/src/main/java/com/volcengine/velive/rn/push/ScreenCaptureHelper.java +0 -73
package/android/build.gradle
CHANGED
|
@@ -87,6 +87,6 @@ dependencies {
|
|
|
87
87
|
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
88
88
|
//noinspection GradleDynamicVersion
|
|
89
89
|
implementation "com.facebook.react:react-native:+"
|
|
90
|
-
implementation "com.volcengine:VolcApiEngine:1.2
|
|
91
|
-
api 'com.bytedanceapi:ttsdk-ttlivepush_rtc:1.
|
|
90
|
+
implementation "com.volcengine:VolcApiEngine:1.6.2"
|
|
91
|
+
api 'com.bytedanceapi:ttsdk-ttlivepush_rtc:1.46.300.2'
|
|
92
92
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
package com.volcengine.velive.rn.push;
|
|
2
|
+
import com.ss.avframework.live.statistics.VeLivePusherStatisticsExt;
|
|
3
|
+
import com.volcengine.VolcApiEngine.runtime.Util;
|
|
4
|
+
|
|
5
|
+
public class ClassHelper {
|
|
6
|
+
public static void init() {
|
|
7
|
+
Util.JsonAbleClass.add(VeLivePusherStatisticsExt.class);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
package com.volcengine.velive.rn.push;
|
|
2
2
|
|
|
3
3
|
import androidx.annotation.NonNull;
|
|
4
|
-
|
|
5
4
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
6
5
|
import com.volcengine.VolcApiEngine.*;
|
|
7
6
|
|
|
8
7
|
public class NativeVariableManager {
|
|
9
|
-
static void init(@NonNull VolcApiEngine apiEngine,
|
|
8
|
+
static void init(@NonNull VolcApiEngine apiEngine,
|
|
9
|
+
ReactApplicationContext reactContext) {
|
|
10
10
|
var m = apiEngine.msgClient.proto.variableManager;
|
|
11
|
-
|
|
12
|
-
m.registerVar("ApplicationContext", (Object[] args) -> reactContext.getApplicationContext());
|
|
13
|
-
m.registerVar("ReactApplicationContext", (Object[] args) -> reactContext);
|
|
14
11
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
m.registerVar("ApplicationContext",
|
|
13
|
+
(Object[] args) -> reactContext.getApplicationContext());
|
|
14
|
+
m.registerVar("ReactApplicationContext", (Object[] args) -> reactContext);
|
|
18
15
|
}
|
|
19
16
|
}
|
|
@@ -4,34 +4,31 @@ import android.graphics.Bitmap;
|
|
|
4
4
|
import android.util.Log;
|
|
5
5
|
import android.view.View;
|
|
6
6
|
import android.view.ViewTreeObserver;
|
|
7
|
-
|
|
8
7
|
import com.ss.avframework.live.VeLivePusher;
|
|
9
8
|
import com.ss.avframework.live.VeLivePusherDef.VeLiveMixVideoLayout;
|
|
10
|
-
import com.ss.avframework.live.VeLivePusherDef.VeLiveStreamMixDescription;
|
|
11
9
|
import com.ss.avframework.live.VeLivePusherDef.VeLivePusherRenderMode;
|
|
10
|
+
import com.ss.avframework.live.VeLivePusherDef.VeLiveStreamMixDescription;
|
|
12
11
|
import com.ss.avframework.live.VeLiveVideoFrame;
|
|
13
|
-
|
|
14
|
-
import org.json.JSONObject;
|
|
15
|
-
|
|
16
12
|
import java.util.HashMap;
|
|
17
13
|
import java.util.Map;
|
|
18
14
|
import java.util.concurrent.ConcurrentHashMap;
|
|
19
|
-
|
|
20
15
|
import javax.annotation.Nullable;
|
|
16
|
+
import org.json.JSONObject;
|
|
21
17
|
|
|
22
18
|
public class MixerManager {
|
|
23
|
-
public
|
|
19
|
+
public static Map<String, View> cachedMixedViews = new HashMap<>();
|
|
24
20
|
|
|
25
21
|
private static final String TAG = "MixerManager";
|
|
26
22
|
|
|
27
23
|
private VeLivePusher pusher;
|
|
28
|
-
private final Map<String, VeLiveMixVideoLayout> mixedViewLayout =
|
|
29
|
-
|
|
30
|
-
private final Map<String, Integer>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
private final Map<String, VeLiveMixVideoLayout> mixedViewLayout =
|
|
25
|
+
new ConcurrentHashMap<>();
|
|
26
|
+
private final Map<String, Integer> viewIdToStreamId =
|
|
27
|
+
new ConcurrentHashMap<>();
|
|
28
|
+
private final Map<String, Integer> pendingCallbacks =
|
|
29
|
+
new ConcurrentHashMap<>();
|
|
30
|
+
|
|
31
|
+
public void setPusher(VeLivePusher pusher) { this.pusher = pusher; }
|
|
35
32
|
|
|
36
33
|
/**
|
|
37
34
|
* Add a view to the mixer
|
|
@@ -40,85 +37,81 @@ public class MixerManager {
|
|
|
40
37
|
* @return streamId for this view
|
|
41
38
|
*/
|
|
42
39
|
public int addView(String viewId, JSONObject viewInfo) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return videoStreamId;
|
|
101
|
-
} catch (Exception e) {
|
|
102
|
-
return -1;
|
|
103
|
-
}
|
|
40
|
+
try {
|
|
41
|
+
if (pusher == null || pusher.getMixerManager() == null) {
|
|
42
|
+
return -1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (viewIdToStreamId.containsKey(viewId)) {
|
|
46
|
+
return viewIdToStreamId.get(viewId);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
int videoStreamId = pusher.getMixerManager().addVideoStream();
|
|
50
|
+
VeLiveStreamMixDescription description = new VeLiveStreamMixDescription();
|
|
51
|
+
VeLiveMixVideoLayout layout = new VeLiveMixVideoLayout();
|
|
52
|
+
layout.x = (float)viewInfo.getDouble("x");
|
|
53
|
+
layout.y = (float)viewInfo.getDouble("y");
|
|
54
|
+
layout.width = (float)viewInfo.getDouble("width");
|
|
55
|
+
layout.height = (float)viewInfo.getDouble("height");
|
|
56
|
+
layout.alpha = (float)viewInfo.optDouble("alpha", 1.0);
|
|
57
|
+
layout.zOrder = viewInfo.optInt("zOrder", 0);
|
|
58
|
+
int renderModeValue = viewInfo.optInt("renderMode", 0);
|
|
59
|
+
VeLivePusherRenderMode[] renderModes = VeLivePusherRenderMode.values();
|
|
60
|
+
if (renderModeValue >= 0 && renderModeValue < renderModes.length) {
|
|
61
|
+
layout.renderMode = renderModes[renderModeValue];
|
|
62
|
+
} else {
|
|
63
|
+
layout.renderMode = VeLivePusherRenderMode.values()[0];
|
|
64
|
+
}
|
|
65
|
+
layout.streamId = videoStreamId;
|
|
66
|
+
description.mixVideoStreams.add(layout);
|
|
67
|
+
mixedViewLayout.put(viewId, layout);
|
|
68
|
+
viewIdToStreamId.put(viewId, videoStreamId);
|
|
69
|
+
pusher.getMixerManager().updateStreamMixDescription(description);
|
|
70
|
+
|
|
71
|
+
View view = cachedMixedViews.get(viewId);
|
|
72
|
+
if (view instanceof MixerView) {
|
|
73
|
+
MixerView mixerView = (MixerView)view;
|
|
74
|
+
setupCallbackForMixerView(mixerView, videoStreamId);
|
|
75
|
+
|
|
76
|
+
android.os.Handler mainHandler =
|
|
77
|
+
new android.os.Handler(android.os.Looper.getMainLooper());
|
|
78
|
+
mainHandler.postDelayed(new Runnable() {
|
|
79
|
+
@Override
|
|
80
|
+
public void run() {
|
|
81
|
+
try {
|
|
82
|
+
mixerView.performManualCapture();
|
|
83
|
+
} catch (Exception e) {
|
|
84
|
+
Log.w(TAG, "Failed to perform manual capture after addView", e);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}, 300);
|
|
88
|
+
} else {
|
|
89
|
+
pendingCallbacks.put(viewId, videoStreamId);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return videoStreamId;
|
|
93
|
+
} catch (Exception e) {
|
|
94
|
+
return -1;
|
|
95
|
+
}
|
|
104
96
|
}
|
|
105
|
-
|
|
97
|
+
|
|
106
98
|
/**
|
|
107
99
|
* Update view configuration
|
|
108
100
|
*/
|
|
109
101
|
public boolean updateView(String viewId, JSONObject viewInfo) {
|
|
110
102
|
try {
|
|
111
103
|
VeLiveMixVideoLayout layout = mixedViewLayout.get(viewId);
|
|
112
|
-
if(layout == null) {
|
|
104
|
+
if (layout == null) {
|
|
113
105
|
return false;
|
|
114
106
|
}
|
|
115
107
|
VeLiveStreamMixDescription description = new VeLiveStreamMixDescription();
|
|
116
|
-
layout.x = (float)
|
|
117
|
-
layout.y = (float)
|
|
118
|
-
layout.width = (float)
|
|
119
|
-
layout.height = (float)
|
|
108
|
+
layout.x = (float)viewInfo.getDouble("x");
|
|
109
|
+
layout.y = (float)viewInfo.getDouble("y");
|
|
110
|
+
layout.width = (float)viewInfo.getDouble("width");
|
|
111
|
+
layout.height = (float)viewInfo.getDouble("height");
|
|
112
|
+
layout.alpha = (float)viewInfo.optDouble("alpha", 1.0);
|
|
120
113
|
Integer streamId = viewIdToStreamId.get(viewId);
|
|
121
|
-
if(streamId != null) {
|
|
114
|
+
if (streamId != null) {
|
|
122
115
|
layout.streamId = streamId;
|
|
123
116
|
}
|
|
124
117
|
if (viewInfo.has("zOrder")) {
|
|
@@ -134,10 +127,22 @@ public class MixerManager {
|
|
|
134
127
|
mixedViewLayout.put(viewId, layout);
|
|
135
128
|
description.mixVideoStreams.add(layout);
|
|
136
129
|
pusher.getMixerManager().updateStreamMixDescription(description);
|
|
130
|
+
|
|
137
131
|
View view = cachedMixedViews.get(viewId);
|
|
138
132
|
if (view instanceof MixerView) {
|
|
139
|
-
MixerView mixerView = (MixerView)
|
|
140
|
-
|
|
133
|
+
MixerView mixerView = (MixerView)view;
|
|
134
|
+
android.os.Handler mainHandler =
|
|
135
|
+
new android.os.Handler(android.os.Looper.getMainLooper());
|
|
136
|
+
mainHandler.postDelayed(new Runnable() {
|
|
137
|
+
@Override
|
|
138
|
+
public void run() {
|
|
139
|
+
try {
|
|
140
|
+
mixerView.performManualCapture();
|
|
141
|
+
} catch (Exception e) {
|
|
142
|
+
Log.w(TAG, "Failed to perform manual capture after update", e);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}, 300);
|
|
141
146
|
}
|
|
142
147
|
return true;
|
|
143
148
|
} catch (Exception e) {
|
|
@@ -154,15 +159,16 @@ public class MixerManager {
|
|
|
154
159
|
if (layout == null) {
|
|
155
160
|
return false;
|
|
156
161
|
}
|
|
157
|
-
|
|
162
|
+
|
|
158
163
|
viewIdToStreamId.remove(viewId);
|
|
159
|
-
|
|
164
|
+
|
|
160
165
|
View view = cachedMixedViews.get(viewId);
|
|
161
166
|
if (view instanceof MixerView) {
|
|
162
|
-
MixerView mixerView = (MixerView)
|
|
167
|
+
MixerView mixerView = (MixerView)view;
|
|
163
168
|
mixerView.setBitmapCaptureCallback(null);
|
|
164
169
|
}
|
|
165
|
-
|
|
170
|
+
cachedMixedViews.remove(viewId);
|
|
171
|
+
|
|
166
172
|
pusher.getMixerManager().removeVideoStream(layout.streamId);
|
|
167
173
|
return true;
|
|
168
174
|
|
|
@@ -177,7 +183,7 @@ public class MixerManager {
|
|
|
177
183
|
public void captureView(String viewId) {
|
|
178
184
|
View view = cachedMixedViews.get(viewId);
|
|
179
185
|
if (view instanceof MixerView) {
|
|
180
|
-
MixerView mixerView = (MixerView)
|
|
186
|
+
MixerView mixerView = (MixerView)view;
|
|
181
187
|
mixerView.performManualCapture();
|
|
182
188
|
}
|
|
183
189
|
}
|
|
@@ -192,28 +198,33 @@ public class MixerManager {
|
|
|
192
198
|
Integer streamId = instance.pendingCallbacks.remove(viewId);
|
|
193
199
|
if (streamId != null) {
|
|
194
200
|
setupCallbackForMixerView(mixerView, streamId);
|
|
195
|
-
|
|
196
|
-
android.os.Handler mainHandler =
|
|
201
|
+
|
|
202
|
+
android.os.Handler mainHandler =
|
|
203
|
+
new android.os.Handler(android.os.Looper.getMainLooper());
|
|
197
204
|
mainHandler.postDelayed(new Runnable() {
|
|
198
205
|
@Override
|
|
199
206
|
public void run() {
|
|
200
207
|
try {
|
|
201
|
-
VeLiveMixVideoLayout layout =
|
|
202
|
-
|
|
203
|
-
|
|
208
|
+
VeLiveMixVideoLayout layout =
|
|
209
|
+
instance.mixedViewLayout.get(viewId);
|
|
210
|
+
if (layout != null && instance.pusher != null &&
|
|
211
|
+
instance.pusher.getMixerManager() != null) {
|
|
212
|
+
VeLiveStreamMixDescription description =
|
|
213
|
+
new VeLiveStreamMixDescription();
|
|
204
214
|
description.mixVideoStreams.add(layout);
|
|
205
|
-
instance.pusher.getMixerManager().updateStreamMixDescription(
|
|
215
|
+
instance.pusher.getMixerManager().updateStreamMixDescription(
|
|
216
|
+
description);
|
|
206
217
|
}
|
|
207
218
|
mixerView.performManualCapture();
|
|
208
219
|
} catch (Exception e) {
|
|
209
|
-
|
|
220
|
+
Log.w(TAG, "Failed to perform operations in onViewReady", e);
|
|
210
221
|
}
|
|
211
222
|
}
|
|
212
|
-
},
|
|
223
|
+
}, 300);
|
|
213
224
|
}
|
|
214
225
|
}
|
|
215
226
|
} catch (Exception e) {
|
|
216
|
-
|
|
227
|
+
Log.w(TAG, "Error in onViewReady", e);
|
|
217
228
|
}
|
|
218
229
|
}
|
|
219
230
|
|
|
@@ -225,18 +236,18 @@ public class MixerManager {
|
|
|
225
236
|
if (bitmap == null || bitmap.isRecycled()) {
|
|
226
237
|
return;
|
|
227
238
|
}
|
|
228
|
-
|
|
239
|
+
|
|
229
240
|
if (pusher == null || pusher.getMixerManager() == null) {
|
|
230
241
|
return;
|
|
231
242
|
}
|
|
232
|
-
|
|
243
|
+
|
|
233
244
|
int width = bitmap.getWidth();
|
|
234
245
|
int height = bitmap.getHeight();
|
|
235
|
-
|
|
246
|
+
|
|
236
247
|
if (width <= 0 || height <= 0) {
|
|
237
248
|
return;
|
|
238
249
|
}
|
|
239
|
-
|
|
250
|
+
|
|
240
251
|
TextureMgr textureMgr = new TextureMgr(width, height);
|
|
241
252
|
textureMgr.dealWithTexture(bitmap, new TextureMgr.RenderListener() {
|
|
242
253
|
@Override
|
|
@@ -245,19 +256,18 @@ public class MixerManager {
|
|
|
245
256
|
if (texture <= 0) {
|
|
246
257
|
return;
|
|
247
258
|
}
|
|
248
|
-
|
|
259
|
+
|
|
249
260
|
long pts = System.currentTimeMillis() * 1000;
|
|
250
|
-
VeLiveVideoFrame videoFrame =
|
|
251
|
-
|
|
261
|
+
VeLiveVideoFrame videoFrame =
|
|
262
|
+
new VeLiveVideoFrame(width, height, pts, texture, false, null);
|
|
263
|
+
|
|
252
264
|
if (pusher != null && pusher.getMixerManager() != null) {
|
|
253
|
-
pusher.getMixerManager().sendCustomVideoFrame(videoFrame,
|
|
265
|
+
pusher.getMixerManager().sendCustomVideoFrame(videoFrame,
|
|
266
|
+
streamId);
|
|
254
267
|
}
|
|
255
268
|
} catch (Exception e) {
|
|
256
269
|
// Ignore
|
|
257
270
|
} finally {
|
|
258
|
-
if (bitmap != null && !bitmap.isRecycled()) {
|
|
259
|
-
bitmap.recycle();
|
|
260
|
-
}
|
|
261
271
|
textureMgr.cleanup();
|
|
262
272
|
}
|
|
263
273
|
}
|
|
@@ -266,16 +276,17 @@ public class MixerManager {
|
|
|
266
276
|
// Ignore
|
|
267
277
|
}
|
|
268
278
|
}
|
|
269
|
-
|
|
279
|
+
|
|
270
280
|
/**
|
|
271
281
|
* Static method to set up callback for MixerView
|
|
272
282
|
* Now with intelligent layout waiting logic
|
|
273
283
|
*/
|
|
274
|
-
private static void setupCallbackForMixerView(MixerView mixerView,
|
|
284
|
+
private static void setupCallbackForMixerView(MixerView mixerView,
|
|
285
|
+
int streamId) {
|
|
275
286
|
if (mixerView == null) {
|
|
276
287
|
return;
|
|
277
288
|
}
|
|
278
|
-
|
|
289
|
+
|
|
279
290
|
mixerView.setBitmapCaptureCallback(new BitmapCaptureCallback() {
|
|
280
291
|
@Override
|
|
281
292
|
public void onBitmapCaptured(Bitmap bitmap) {
|
|
@@ -289,13 +300,13 @@ public class MixerManager {
|
|
|
289
300
|
// Ignore
|
|
290
301
|
}
|
|
291
302
|
}
|
|
292
|
-
|
|
303
|
+
|
|
293
304
|
@Override
|
|
294
305
|
public void onCaptureError(String error) {
|
|
295
306
|
// Ignore
|
|
296
307
|
}
|
|
297
308
|
});
|
|
298
|
-
|
|
309
|
+
|
|
299
310
|
if (mixerView.getWidth() > 0 && mixerView.getHeight() > 0) {
|
|
300
311
|
try {
|
|
301
312
|
mixerView.performManualCapture();
|
|
@@ -303,32 +314,36 @@ public class MixerManager {
|
|
|
303
314
|
// Ignore
|
|
304
315
|
}
|
|
305
316
|
} else {
|
|
306
|
-
ViewTreeObserver.OnGlobalLayoutListener layoutListener =
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
317
|
+
ViewTreeObserver.OnGlobalLayoutListener layoutListener =
|
|
318
|
+
new ViewTreeObserver.OnGlobalLayoutListener() {
|
|
319
|
+
@Override
|
|
320
|
+
public void onGlobalLayout() {
|
|
321
|
+
try {
|
|
322
|
+
if (mixerView.getViewTreeObserver().isAlive()) {
|
|
323
|
+
if (mixerView.getWidth() > 0 && mixerView.getHeight() > 0) {
|
|
324
|
+
mixerView.getViewTreeObserver()
|
|
325
|
+
.removeOnGlobalLayoutListener(this);
|
|
326
|
+
mixerView.performManualCapture();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
} catch (Exception e) {
|
|
330
|
+
// Ignore
|
|
314
331
|
}
|
|
315
332
|
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
|
|
333
|
+
};
|
|
334
|
+
|
|
322
335
|
try {
|
|
323
|
-
mixerView.getViewTreeObserver().addOnGlobalLayoutListener(
|
|
336
|
+
mixerView.getViewTreeObserver().addOnGlobalLayoutListener(
|
|
337
|
+
layoutListener);
|
|
324
338
|
} catch (Exception e) {
|
|
325
339
|
// Ignore
|
|
326
340
|
}
|
|
327
341
|
}
|
|
328
342
|
}
|
|
329
|
-
|
|
343
|
+
|
|
330
344
|
/**
|
|
331
|
-
* Static version of sendBitmapToMixer - finds the active MixerManager
|
|
345
|
+
* Static version of sendBitmapToMixer - finds the active MixerManager
|
|
346
|
+
* instance
|
|
332
347
|
*/
|
|
333
348
|
private static void sendBitmapToMixerStatic(int streamId, Bitmap bitmap) {
|
|
334
349
|
try {
|
|
@@ -340,7 +355,7 @@ public class MixerManager {
|
|
|
340
355
|
// Ignore
|
|
341
356
|
}
|
|
342
357
|
}
|
|
343
|
-
|
|
358
|
+
|
|
344
359
|
/**
|
|
345
360
|
* Find the active MixerManager instance
|
|
346
361
|
*/
|
|
@@ -351,44 +366,42 @@ public class MixerManager {
|
|
|
351
366
|
}
|
|
352
367
|
return null;
|
|
353
368
|
}
|
|
354
|
-
|
|
369
|
+
|
|
355
370
|
private static volatile MixerManager currentInstance;
|
|
356
|
-
|
|
371
|
+
|
|
357
372
|
public MixerManager() {
|
|
358
|
-
synchronized (MixerManager.class) {
|
|
359
|
-
currentInstance = this;
|
|
360
|
-
}
|
|
373
|
+
synchronized (MixerManager.class) { currentInstance = this; }
|
|
361
374
|
}
|
|
362
|
-
|
|
375
|
+
|
|
363
376
|
/**
|
|
364
|
-
*
|
|
377
|
+
* cleanup method to release resources
|
|
365
378
|
*/
|
|
366
379
|
public void cleanup() {
|
|
367
380
|
try {
|
|
368
381
|
for (String viewId : cachedMixedViews.keySet()) {
|
|
369
382
|
View view = cachedMixedViews.get(viewId);
|
|
370
383
|
if (view instanceof MixerView) {
|
|
371
|
-
MixerView mixerView = (MixerView)
|
|
384
|
+
MixerView mixerView = (MixerView)view;
|
|
372
385
|
mixerView.setBitmapCaptureCallback(null);
|
|
373
386
|
}
|
|
374
387
|
}
|
|
375
|
-
|
|
388
|
+
|
|
376
389
|
mixedViewLayout.clear();
|
|
377
390
|
viewIdToStreamId.clear();
|
|
378
391
|
pendingCallbacks.clear();
|
|
379
|
-
|
|
392
|
+
|
|
380
393
|
synchronized (MixerManager.class) {
|
|
381
394
|
if (currentInstance == this) {
|
|
382
395
|
currentInstance = null;
|
|
383
396
|
}
|
|
384
397
|
}
|
|
385
|
-
|
|
398
|
+
|
|
386
399
|
pusher = null;
|
|
387
400
|
} catch (Exception e) {
|
|
388
401
|
// Ignore
|
|
389
402
|
}
|
|
390
403
|
}
|
|
391
|
-
|
|
404
|
+
|
|
392
405
|
// Callback interface for bitmap capture
|
|
393
406
|
public interface BitmapCaptureCallback {
|
|
394
407
|
void onBitmapCaptured(Bitmap bitmap);
|
|
@@ -150,7 +150,7 @@ public class MixerView extends FrameLayout {
|
|
|
150
150
|
|
|
151
151
|
private void startRealtimeCapture() {
|
|
152
152
|
long interval = (long)(1000f / captureFramerate);
|
|
153
|
-
|
|
153
|
+
|
|
154
154
|
captureRunnable = new Runnable() {
|
|
155
155
|
@Override
|
|
156
156
|
public void run() {
|
|
@@ -260,7 +260,7 @@ public class MixerView extends FrameLayout {
|
|
|
260
260
|
return;
|
|
261
261
|
}
|
|
262
262
|
lastCaptureTime = currentTime;
|
|
263
|
-
|
|
263
|
+
|
|
264
264
|
synchronized (captureLock) {
|
|
265
265
|
if (isCapturing.compareAndSet(false, true)) {
|
|
266
266
|
Bitmap bitmap = null;
|
|
@@ -271,9 +271,16 @@ public class MixerView extends FrameLayout {
|
|
|
271
271
|
}
|
|
272
272
|
} catch (OutOfMemoryError e) {
|
|
273
273
|
System.gc();
|
|
274
|
+
// If an OOM occurs and the bitmap has not been passed to
|
|
275
|
+
// processBitmap, recycle it
|
|
276
|
+
if (bitmap != null && !bitmap.isRecycled()) {
|
|
277
|
+
bitmap.recycle();
|
|
278
|
+
}
|
|
279
|
+
} catch (Exception e) {
|
|
280
|
+
// If any other exception occurs and the bitmap has not been passed to
|
|
281
|
+
// processBitmap, recycle it
|
|
274
282
|
if (bitmap != null && !bitmap.isRecycled()) {
|
|
275
283
|
bitmap.recycle();
|
|
276
|
-
bitmap = null;
|
|
277
284
|
}
|
|
278
285
|
} finally {
|
|
279
286
|
isCapturing.set(false);
|
|
@@ -313,7 +320,7 @@ public class MixerView extends FrameLayout {
|
|
|
313
320
|
}
|
|
314
321
|
return;
|
|
315
322
|
}
|
|
316
|
-
|
|
323
|
+
|
|
317
324
|
// Call callback first if set (for MixerManager)
|
|
318
325
|
if (bitmapCaptureCallback != null) {
|
|
319
326
|
try {
|
|
@@ -321,7 +328,8 @@ public class MixerView extends FrameLayout {
|
|
|
321
328
|
bitmapCaptureCallback.onBitmapCaptured(bitmap);
|
|
322
329
|
} catch (Exception e) {
|
|
323
330
|
if (bitmapCaptureCallback != null) {
|
|
324
|
-
bitmapCaptureCallback.onCaptureError("Callback error: " +
|
|
331
|
+
bitmapCaptureCallback.onCaptureError("Callback error: " +
|
|
332
|
+
e.getMessage());
|
|
325
333
|
}
|
|
326
334
|
}
|
|
327
335
|
} else {
|
|
@@ -341,19 +349,23 @@ public class MixerView extends FrameLayout {
|
|
|
341
349
|
} catch (IllegalStateException e) {
|
|
342
350
|
// Ignore
|
|
343
351
|
}
|
|
344
|
-
|
|
345
|
-
// if no callback, recycle immediately to avoid accumulation
|
|
346
|
-
if (bitmap != null && !bitmap.isRecycled()) {
|
|
347
|
-
bitmap.recycle();
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
352
|
}
|
|
351
353
|
|
|
352
354
|
// Clean up old bitmap
|
|
353
355
|
if (lastBitmap != null && !lastBitmap.isRecycled()) {
|
|
354
356
|
lastBitmap.recycle();
|
|
355
357
|
}
|
|
356
|
-
|
|
358
|
+
|
|
359
|
+
// 如果没有设置回调,立即释放当前 bitmap 以避免内存累积
|
|
360
|
+
// 如果设置了回调,bitmap 将由回调的接收方负责管理
|
|
361
|
+
if (bitmapCaptureCallback == null) {
|
|
362
|
+
if (bitmap != null && !bitmap.isRecycled()) {
|
|
363
|
+
bitmap.recycle();
|
|
364
|
+
}
|
|
365
|
+
lastBitmap = null;
|
|
366
|
+
} else {
|
|
367
|
+
lastBitmap = bitmap;
|
|
368
|
+
}
|
|
357
369
|
}
|
|
358
370
|
|
|
359
371
|
public void handleCommand(String command, @Nullable ReadableArray args) {
|
|
@@ -384,7 +396,7 @@ public class MixerView extends FrameLayout {
|
|
|
384
396
|
MixerManager.onViewReady(viewId, this);
|
|
385
397
|
}
|
|
386
398
|
}
|
|
387
|
-
|
|
399
|
+
|
|
388
400
|
@Override
|
|
389
401
|
protected void onDetachedFromWindow() {
|
|
390
402
|
super.onDetachedFromWindow();
|
|
@@ -393,24 +405,23 @@ public class MixerView extends FrameLayout {
|
|
|
393
405
|
}
|
|
394
406
|
cleanup();
|
|
395
407
|
}
|
|
396
|
-
|
|
397
|
-
public void setViewId(String viewId) {
|
|
398
|
-
this.viewId = viewId;
|
|
408
|
+
|
|
409
|
+
public void setViewId(String viewId) {
|
|
410
|
+
this.viewId = viewId;
|
|
399
411
|
MixerManager.cachedMixedViews.put(viewId, this);
|
|
400
412
|
// 通知MixerManager视图已准备好,检查是否有待处理的回调
|
|
401
413
|
MixerManager.onViewReady(viewId, this);
|
|
402
414
|
}
|
|
403
415
|
|
|
404
416
|
// Add callback support for MixerManager integration
|
|
405
|
-
public void
|
|
417
|
+
public void
|
|
418
|
+
setBitmapCaptureCallback(MixerManager.BitmapCaptureCallback callback) {
|
|
406
419
|
this.bitmapCaptureCallback = callback;
|
|
407
420
|
}
|
|
408
421
|
|
|
409
422
|
// Public method for manual capture (called by MixerManager)
|
|
410
|
-
public void performManualCapture() {
|
|
411
|
-
|
|
412
|
-
}
|
|
413
|
-
|
|
423
|
+
public void performManualCapture() { performCapture("manual"); }
|
|
424
|
+
|
|
414
425
|
private void cleanup() {
|
|
415
426
|
isDestroyed.set(true);
|
|
416
427
|
stopCapture();
|
|
@@ -420,4 +431,4 @@ public class MixerView extends FrameLayout {
|
|
|
420
431
|
lastBitmap = null;
|
|
421
432
|
}
|
|
422
433
|
}
|
|
423
|
-
}
|
|
434
|
+
}
|