@byteplus/react-native-live-push 1.1.3-rc.1 → 1.1.3-rc.2

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.
Files changed (123) hide show
  1. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushModule.java +13 -2
  2. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushPackage.java +16 -13
  3. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushView.java +16 -0
  4. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushViewManager.java +7 -2
  5. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerManager.java +392 -0
  6. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerView.java +415 -0
  7. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerViewManager.java +79 -0
  8. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/TextureMgr.java +168 -0
  9. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/YuvHelper.java +154 -0
  10. package/ios/VeLiveMixerHelper.h +44 -0
  11. package/ios/VeLiveMixerHelper.m +562 -0
  12. package/ios/VeLiveMixerView.h +69 -0
  13. package/ios/VeLiveMixerView.m +592 -0
  14. package/ios/VeLiveMixerViewManager.m +92 -0
  15. package/lib/commonjs/index.js +1779 -980
  16. package/lib/commonjs/typescript/android/index.d.ts +47 -0
  17. package/lib/commonjs/typescript/codegen/android/api.d.ts +1527 -0
  18. package/lib/commonjs/typescript/codegen/android/callback.d.ts +91 -0
  19. package/lib/commonjs/typescript/codegen/android/errorcode.d.ts +26 -0
  20. package/lib/commonjs/typescript/codegen/android/index.d.ts +5 -0
  21. package/lib/commonjs/typescript/codegen/android/keytype.d.ts +846 -0
  22. package/lib/commonjs/typescript/codegen/android/types.d.ts +33 -0
  23. package/lib/commonjs/typescript/codegen/ios/api.d.ts +222 -0
  24. package/lib/commonjs/typescript/codegen/ios/callback.d.ts +80 -0
  25. package/lib/commonjs/typescript/codegen/ios/errorcode.d.ts +54 -0
  26. package/lib/commonjs/typescript/codegen/ios/external.d.ts +1 -0
  27. package/lib/commonjs/typescript/codegen/ios/index.d.ts +6 -0
  28. package/lib/commonjs/typescript/codegen/ios/keytype.d.ts +460 -0
  29. package/lib/commonjs/typescript/codegen/ios/types.d.ts +46 -0
  30. package/lib/commonjs/typescript/codegen/pack/api.d.ts +1835 -0
  31. package/lib/commonjs/typescript/codegen/pack/callback.d.ts +400 -0
  32. package/lib/commonjs/typescript/codegen/pack/errorcode.d.ts +35 -0
  33. package/lib/commonjs/typescript/codegen/pack/index.d.ts +5 -0
  34. package/lib/commonjs/typescript/codegen/pack/keytype.d.ts +1392 -0
  35. package/lib/commonjs/typescript/codegen/pack/types.d.ts +68 -0
  36. package/lib/commonjs/typescript/codegen/type-shim.d.ts +6 -0
  37. package/lib/commonjs/typescript/component.d.ts +15 -0
  38. package/lib/commonjs/typescript/core/api.d.ts +17 -0
  39. package/lib/commonjs/typescript/core/callback.d.ts +2 -0
  40. package/lib/commonjs/typescript/core/env.d.ts +29 -0
  41. package/lib/commonjs/typescript/core/errorcode.d.ts +2 -0
  42. package/lib/commonjs/typescript/core/index.d.ts +6 -0
  43. package/lib/commonjs/typescript/core/keytype.d.ts +17 -0
  44. package/lib/commonjs/typescript/core/mixer.d.ts +26 -0
  45. package/lib/commonjs/typescript/core/pusher.d.ts +16 -0
  46. package/lib/commonjs/typescript/index.d.ts +3 -0
  47. package/lib/commonjs/typescript/ios/extends.d.ts +41 -0
  48. package/lib/commonjs/typescript/platforms/android/extends.d.ts +8 -0
  49. package/lib/commonjs/typescript/platforms/android/helper.d.ts +8 -0
  50. package/lib/commonjs/typescript/platforms/android/mixer.d.ts +8 -0
  51. package/lib/commonjs/typescript/platforms/ios/extends.d.ts +17 -0
  52. package/lib/commonjs/typescript/platforms/ios/helper.d.ts +8 -0
  53. package/lib/commonjs/typescript/platforms/ios/mixer.d.ts +9 -0
  54. package/lib/commonjs/typescript/runtime.d.ts +1 -0
  55. package/lib/commonjs/typescript/view/MixView.d.ts +52 -0
  56. package/lib/commonjs/typescript/view/VeImageView.d.ts +19 -0
  57. package/lib/commonjs/typescript/view/VeTextView.d.ts +7 -0
  58. package/lib/commonjs/typescript/view/VeView.d.ts +7 -0
  59. package/lib/commonjs/typescript/view/VeWebView.d.ts +7 -0
  60. package/lib/commonjs/typescript/view/index.d.ts +5 -0
  61. package/lib/module/index.js +1776 -982
  62. package/lib/module/typescript/android/index.d.ts +47 -0
  63. package/lib/module/typescript/codegen/android/api.d.ts +1527 -0
  64. package/lib/module/typescript/codegen/android/callback.d.ts +91 -0
  65. package/lib/module/typescript/codegen/android/errorcode.d.ts +26 -0
  66. package/lib/module/typescript/codegen/android/index.d.ts +5 -0
  67. package/lib/module/typescript/codegen/android/keytype.d.ts +846 -0
  68. package/lib/module/typescript/codegen/android/types.d.ts +33 -0
  69. package/lib/module/typescript/codegen/ios/api.d.ts +222 -0
  70. package/lib/module/typescript/codegen/ios/callback.d.ts +80 -0
  71. package/lib/module/typescript/codegen/ios/errorcode.d.ts +54 -0
  72. package/lib/module/typescript/codegen/ios/external.d.ts +1 -0
  73. package/lib/module/typescript/codegen/ios/index.d.ts +6 -0
  74. package/lib/module/typescript/codegen/ios/keytype.d.ts +460 -0
  75. package/lib/module/typescript/codegen/ios/types.d.ts +46 -0
  76. package/lib/module/typescript/codegen/pack/api.d.ts +1835 -0
  77. package/lib/module/typescript/codegen/pack/callback.d.ts +400 -0
  78. package/lib/module/typescript/codegen/pack/errorcode.d.ts +35 -0
  79. package/lib/module/typescript/codegen/pack/index.d.ts +5 -0
  80. package/lib/module/typescript/codegen/pack/keytype.d.ts +1392 -0
  81. package/lib/module/typescript/codegen/pack/types.d.ts +68 -0
  82. package/lib/module/typescript/codegen/type-shim.d.ts +6 -0
  83. package/lib/module/typescript/component.d.ts +15 -0
  84. package/lib/module/typescript/core/api.d.ts +17 -0
  85. package/lib/module/typescript/core/callback.d.ts +2 -0
  86. package/lib/module/typescript/core/env.d.ts +29 -0
  87. package/lib/module/typescript/core/errorcode.d.ts +2 -0
  88. package/lib/module/typescript/core/index.d.ts +6 -0
  89. package/lib/module/typescript/core/keytype.d.ts +17 -0
  90. package/lib/module/typescript/core/mixer.d.ts +26 -0
  91. package/lib/module/typescript/core/pusher.d.ts +16 -0
  92. package/lib/module/typescript/index.d.ts +3 -0
  93. package/lib/module/typescript/ios/extends.d.ts +41 -0
  94. package/lib/module/typescript/platforms/android/extends.d.ts +8 -0
  95. package/lib/module/typescript/platforms/android/helper.d.ts +8 -0
  96. package/lib/module/typescript/platforms/android/mixer.d.ts +8 -0
  97. package/lib/module/typescript/platforms/ios/extends.d.ts +17 -0
  98. package/lib/module/typescript/platforms/ios/helper.d.ts +8 -0
  99. package/lib/module/typescript/platforms/ios/mixer.d.ts +9 -0
  100. package/lib/module/typescript/runtime.d.ts +1 -0
  101. package/lib/module/typescript/view/MixView.d.ts +52 -0
  102. package/lib/module/typescript/view/VeImageView.d.ts +19 -0
  103. package/lib/module/typescript/view/VeTextView.d.ts +7 -0
  104. package/lib/module/typescript/view/VeView.d.ts +7 -0
  105. package/lib/module/typescript/view/VeWebView.d.ts +7 -0
  106. package/lib/module/typescript/view/index.d.ts +5 -0
  107. package/lib/typescript/codegen/android/api.d.ts +1 -121
  108. package/lib/typescript/codegen/ios/api.d.ts +1 -28
  109. package/lib/typescript/codegen/pack/api.d.ts +1 -133
  110. package/lib/typescript/core/api.d.ts +17 -2
  111. package/lib/typescript/core/keytype.d.ts +15 -0
  112. package/lib/typescript/core/mixer.d.ts +26 -0
  113. package/lib/typescript/index.d.ts +1 -0
  114. package/lib/typescript/platforms/android/extends.d.ts +8 -0
  115. package/lib/typescript/platforms/android/mixer.d.ts +8 -0
  116. package/lib/typescript/platforms/ios/mixer.d.ts +9 -0
  117. package/lib/typescript/view/MixView.d.ts +52 -0
  118. package/lib/typescript/view/VeImageView.d.ts +19 -0
  119. package/lib/typescript/view/VeTextView.d.ts +7 -0
  120. package/lib/typescript/view/VeView.d.ts +7 -0
  121. package/lib/typescript/view/VeWebView.d.ts +7 -0
  122. package/lib/typescript/view/index.d.ts +5 -0
  123. package/package.json +1 -1
@@ -0,0 +1,415 @@
1
+ package com.volcengine.velive.rn.push.mixer;
2
+
3
+ import android.graphics.Bitmap;
4
+ import android.graphics.Canvas;
5
+ import android.os.Handler;
6
+ import android.os.Looper;
7
+ import android.view.ViewTreeObserver;
8
+ import android.widget.FrameLayout;
9
+ import androidx.annotation.Nullable;
10
+ import com.facebook.react.bridge.Arguments;
11
+ import com.facebook.react.bridge.ReadableArray;
12
+ import com.facebook.react.bridge.WritableMap;
13
+ import com.facebook.react.uimanager.ThemedReactContext;
14
+ import java.util.concurrent.atomic.AtomicBoolean;
15
+
16
+ /**
17
+ * Custom MixerView that supports different capture modes
18
+ */
19
+ public class MixerView extends FrameLayout {
20
+ private ThemedReactContext context;
21
+ private String viewId;
22
+
23
+ // Mix configuration
24
+ private float mixX = 0f;
25
+ private float mixY = 0f;
26
+ private float mixWidth = 0f;
27
+ private float mixHeight = 0f;
28
+ private int mixZOrder = 0;
29
+ private int mixRenderMode = 0;
30
+
31
+ // Capture configuration
32
+ private String captureMode = "onchange";
33
+ private float captureFramerate = 30f;
34
+ private float autoSensitivity = 5f;
35
+
36
+ // Capture state
37
+ private Handler captureHandler;
38
+ private Runnable captureRunnable;
39
+ private ViewTreeObserver.OnGlobalLayoutListener layoutListener;
40
+ private ViewTreeObserver.OnDrawListener drawListener;
41
+ private AtomicBoolean isCapturing = new AtomicBoolean(false);
42
+ private AtomicBoolean isDestroyed = new AtomicBoolean(false);
43
+
44
+ // Performance optimization
45
+ private Bitmap lastBitmap;
46
+ private long lastCaptureTime = 0;
47
+ private final Object captureLock = new Object();
48
+
49
+ // Auto mode state
50
+ private int changeCount = 0;
51
+ private long windowStartTime = 0;
52
+ private boolean isInRealtimeMode = false;
53
+ private static final long AUTO_WINDOW_MS = 2000; // 2 second window
54
+ private static final int HIGH_CHANGE_THRESHOLD = 10;
55
+ private static final int LOW_CHANGE_THRESHOLD = 2;
56
+
57
+ // Add callback support for MixerManager integration
58
+ private MixerManager.BitmapCaptureCallback bitmapCaptureCallback;
59
+
60
+ public MixerView(ThemedReactContext context) {
61
+ super(context);
62
+ this.context = context;
63
+ this.captureHandler = new Handler(Looper.getMainLooper());
64
+ initializeCapture();
65
+ }
66
+
67
+ private void initializeCapture() {
68
+ // Initialize layout change listener
69
+ layoutListener = this::onViewChanged;
70
+
71
+ // Initialize draw listener for auto mode
72
+ drawListener = this::onViewDraw;
73
+ }
74
+
75
+ // Setters for mix configuration
76
+ public void setMixX(float x) { this.mixX = x; }
77
+ public void setMixY(float y) { this.mixY = y; }
78
+ public void setMixWidth(float width) { this.mixWidth = width; }
79
+ public void setMixHeight(float height) { this.mixHeight = height; }
80
+ public void setMixZOrder(int zOrder) { this.mixZOrder = zOrder; }
81
+ public void setMixRenderMode(int renderMode) {
82
+ this.mixRenderMode = renderMode;
83
+ }
84
+
85
+ public void setCaptureMode(String mode) {
86
+ if (mode.equals(this.captureMode))
87
+ return;
88
+
89
+ stopCapture();
90
+ this.captureMode = mode;
91
+ startCapture();
92
+ }
93
+
94
+ public void setCaptureFramerate(float framerate) {
95
+ this.captureFramerate = Math.max(1f, Math.min(60f, framerate));
96
+ if ("realtime".equals(captureMode)) {
97
+ restartRealtimeCapture();
98
+ }
99
+ }
100
+
101
+ public void setAutoSensitivity(float sensitivity) {
102
+ this.autoSensitivity = Math.max(1f, Math.min(10f, sensitivity));
103
+ }
104
+
105
+ private void startCapture() {
106
+ if (isDestroyed.get())
107
+ return;
108
+
109
+ switch (captureMode) {
110
+ case "onchange":
111
+ startOnChangeCapture();
112
+ break;
113
+ case "realtime":
114
+ startRealtimeCapture();
115
+ break;
116
+ case "auto":
117
+ startAutoCapture();
118
+ break;
119
+ case "manual":
120
+ // Manual mode doesn't auto-start
121
+ break;
122
+ }
123
+ }
124
+
125
+ private void stopCapture() {
126
+ // Remove listeners
127
+ if (getViewTreeObserver().isAlive()) {
128
+ if (layoutListener != null) {
129
+ getViewTreeObserver().removeOnGlobalLayoutListener(layoutListener);
130
+ }
131
+ if (drawListener != null) {
132
+ getViewTreeObserver().removeOnDrawListener(drawListener);
133
+ }
134
+ }
135
+
136
+ // Stop realtime capture
137
+ if (captureRunnable != null) {
138
+ captureHandler.removeCallbacks(captureRunnable);
139
+ captureRunnable = null;
140
+ }
141
+
142
+ isCapturing.set(false);
143
+ }
144
+
145
+ private void startOnChangeCapture() {
146
+ if (getViewTreeObserver().isAlive()) {
147
+ getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
148
+ }
149
+ }
150
+
151
+ private void startRealtimeCapture() {
152
+ long interval = (long)(1000f / captureFramerate);
153
+
154
+ captureRunnable = new Runnable() {
155
+ @Override
156
+ public void run() {
157
+ if (!isDestroyed.get() && "realtime".equals(captureMode)) {
158
+ performCapture("realtime");
159
+ captureHandler.postDelayed(this, interval);
160
+ }
161
+ }
162
+ };
163
+ captureHandler.postDelayed(captureRunnable, interval);
164
+ }
165
+
166
+ private void restartRealtimeCapture() {
167
+ if ("realtime".equals(captureMode)) {
168
+ stopCapture();
169
+ startRealtimeCapture();
170
+ }
171
+ }
172
+
173
+ private void startAutoCapture() {
174
+ // Start with onchange mode
175
+ isInRealtimeMode = false;
176
+ windowStartTime = System.currentTimeMillis();
177
+ changeCount = 0;
178
+
179
+ if (getViewTreeObserver().isAlive()) {
180
+ getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
181
+ getViewTreeObserver().addOnDrawListener(drawListener);
182
+ }
183
+ }
184
+
185
+ private void onViewChanged() {
186
+ if (isDestroyed.get()) {
187
+ return;
188
+ }
189
+
190
+ switch (captureMode) {
191
+ case "onchange":
192
+ performCapture("onchange");
193
+ break;
194
+ case "auto":
195
+ handleAutoModeChange();
196
+ break;
197
+ }
198
+ }
199
+
200
+ private void onViewDraw() {
201
+ if (isDestroyed.get() || !"auto".equals(captureMode))
202
+ return;
203
+
204
+ // Count draws for auto mode sensitivity
205
+ changeCount++;
206
+
207
+ long currentTime = System.currentTimeMillis();
208
+ if (currentTime - windowStartTime >= AUTO_WINDOW_MS) {
209
+ evaluateAutoMode();
210
+ // Reset window
211
+ windowStartTime = currentTime;
212
+ changeCount = 0;
213
+ }
214
+ }
215
+
216
+ private void handleAutoModeChange() {
217
+ if (!isInRealtimeMode) {
218
+ performCapture("auto_onchange");
219
+ }
220
+ }
221
+
222
+ private void evaluateAutoMode() {
223
+ float changesPerSecond = changeCount * 1000f / AUTO_WINDOW_MS;
224
+ float threshold = autoSensitivity;
225
+
226
+ boolean shouldBeRealtime =
227
+ changesPerSecond > (HIGH_CHANGE_THRESHOLD / threshold);
228
+ boolean shouldBeOnChange =
229
+ changesPerSecond < (LOW_CHANGE_THRESHOLD / threshold);
230
+
231
+ if (shouldBeRealtime && !isInRealtimeMode) {
232
+ switchToRealtimeMode();
233
+ } else if (shouldBeOnChange && isInRealtimeMode) {
234
+ switchToOnChangeMode();
235
+ }
236
+ }
237
+
238
+ private void switchToRealtimeMode() {
239
+ isInRealtimeMode = true;
240
+ startRealtimeCapture();
241
+ }
242
+
243
+ private void switchToOnChangeMode() {
244
+ isInRealtimeMode = false;
245
+ // Stop realtime capture but keep layout listener
246
+ if (captureRunnable != null) {
247
+ captureHandler.removeCallbacks(captureRunnable);
248
+ captureRunnable = null;
249
+ }
250
+ }
251
+
252
+ private void performCapture(String trigger) {
253
+ if (isCapturing.get() || isDestroyed.get()) {
254
+ return;
255
+ }
256
+
257
+ long currentTime = System.currentTimeMillis();
258
+ if (currentTime - lastCaptureTime < 16) {
259
+ return;
260
+ }
261
+ lastCaptureTime = currentTime;
262
+
263
+ synchronized (captureLock) {
264
+ if (isCapturing.compareAndSet(false, true)) {
265
+ Bitmap bitmap = null;
266
+ try {
267
+ bitmap = createBitmap();
268
+ if (bitmap != null) {
269
+ processBitmap(bitmap, trigger);
270
+ }
271
+ } catch (OutOfMemoryError e) {
272
+ System.gc();
273
+ if (bitmap != null && !bitmap.isRecycled()) {
274
+ bitmap.recycle();
275
+ bitmap = null;
276
+ }
277
+ } finally {
278
+ isCapturing.set(false);
279
+ }
280
+ }
281
+ }
282
+ }
283
+
284
+ private Bitmap createBitmap() {
285
+ if (getWidth() <= 0 || getHeight() <= 0)
286
+ return null;
287
+
288
+ try {
289
+ Bitmap bitmap =
290
+ Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
291
+ Canvas canvas = new Canvas(bitmap);
292
+ draw(canvas);
293
+ return bitmap;
294
+ } catch (OutOfMemoryError e) {
295
+ // Try with lower quality
296
+ try {
297
+ Bitmap bitmap =
298
+ Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.RGB_565);
299
+ Canvas canvas = new Canvas(bitmap);
300
+ draw(canvas);
301
+ return bitmap;
302
+ } catch (Exception ex) {
303
+ return null;
304
+ }
305
+ }
306
+ }
307
+
308
+ private void processBitmap(Bitmap bitmap, String trigger) {
309
+ if (bitmap == null || bitmap.isRecycled()) {
310
+ if (bitmapCaptureCallback != null) {
311
+ bitmapCaptureCallback.onCaptureError("Bitmap is null or recycled");
312
+ }
313
+ return;
314
+ }
315
+
316
+ // Call callback first if set (for MixerManager)
317
+ if (bitmapCaptureCallback != null) {
318
+ try {
319
+ bitmapCaptureCallback.onBitmapCaptured(bitmap);
320
+ } catch (Exception e) {
321
+ if (bitmapCaptureCallback != null) {
322
+ bitmapCaptureCallback.onCaptureError("Callback error: " + e.getMessage());
323
+ }
324
+ }
325
+ } else {
326
+ // Send event to JS (existing functionality)
327
+ try {
328
+ WritableMap event = Arguments.createMap();
329
+ event.putString("trigger", trigger);
330
+ event.putBoolean("success", true);
331
+ event.putDouble("x", mixX);
332
+ event.putDouble("y", mixY);
333
+ event.putDouble("width", mixWidth);
334
+ event.putDouble("height", mixHeight);
335
+ event.putInt("zOrder", mixZOrder);
336
+ event.putInt("renderMode", mixRenderMode);
337
+ event.putInt("bitmapWidth", bitmap.getWidth());
338
+ event.putInt("bitmapHeight", bitmap.getHeight());
339
+ } catch (IllegalStateException e) {
340
+ // Ignore
341
+ }
342
+ }
343
+
344
+ // Clean up old bitmap
345
+ if (lastBitmap != null && !lastBitmap.isRecycled()) {
346
+ lastBitmap.recycle();
347
+ }
348
+ lastBitmap = bitmap;
349
+ }
350
+
351
+ public void handleCommand(String command, @Nullable ReadableArray args) {
352
+ switch (command) {
353
+ case "capture":
354
+ performCapture("manual");
355
+ break;
356
+ case "startCapture":
357
+ startCapture();
358
+ break;
359
+ case "stopCapture":
360
+ stopCapture();
361
+ break;
362
+ case "setCaptureMode":
363
+ if (args != null && args.size() > 0) {
364
+ setCaptureMode(args.getString(0));
365
+ }
366
+ break;
367
+ }
368
+ }
369
+
370
+ @Override
371
+ protected void onAttachedToWindow() {
372
+ super.onAttachedToWindow();
373
+ if (viewId != null) {
374
+ MixerManager.cachedMixedViews.put(viewId, this);
375
+ // 通知MixerManager视图已准备好,检查是否有待处理的回调
376
+ MixerManager.onViewReady(viewId, this);
377
+ }
378
+ }
379
+
380
+ @Override
381
+ protected void onDetachedFromWindow() {
382
+ super.onDetachedFromWindow();
383
+ if (viewId != null) {
384
+ MixerManager.cachedMixedViews.remove(viewId);
385
+ }
386
+ cleanup();
387
+ }
388
+
389
+ public void setViewId(String viewId) {
390
+ this.viewId = viewId;
391
+ MixerManager.cachedMixedViews.put(viewId, this);
392
+ // 通知MixerManager视图已准备好,检查是否有待处理的回调
393
+ MixerManager.onViewReady(viewId, this);
394
+ }
395
+
396
+ // Add callback support for MixerManager integration
397
+ public void setBitmapCaptureCallback(MixerManager.BitmapCaptureCallback callback) {
398
+ this.bitmapCaptureCallback = callback;
399
+ }
400
+
401
+ // Public method for manual capture (called by MixerManager)
402
+ public void performManualCapture() {
403
+ performCapture("manual");
404
+ }
405
+
406
+ private void cleanup() {
407
+ isDestroyed.set(true);
408
+ stopCapture();
409
+
410
+ if (lastBitmap != null && !lastBitmap.isRecycled()) {
411
+ lastBitmap.recycle();
412
+ lastBitmap = null;
413
+ }
414
+ }
415
+ }
@@ -0,0 +1,79 @@
1
+ package com.volcengine.velive.rn.push.mixer;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import androidx.annotation.Nullable;
5
+ import com.facebook.react.uimanager.ViewGroupManager;
6
+ import com.facebook.react.uimanager.ThemedReactContext;
7
+ import com.facebook.react.uimanager.annotations.ReactProp;
8
+
9
+ public class MixerViewManager extends ViewGroupManager<MixerView> {
10
+ public static final String NAME = "VeLiveMixView";
11
+
12
+ @NonNull
13
+ @Override
14
+ public String getName() {
15
+ return NAME;
16
+ }
17
+
18
+ @NonNull
19
+ @Override
20
+ protected MixerView
21
+ createViewInstance(@NonNull ThemedReactContext reactContext) {
22
+ return new MixerView(reactContext);
23
+ }
24
+
25
+ // Props for mixing configuration
26
+ @ReactProp(name = "x", defaultFloat = 0f)
27
+ public void setX(MixerView view, float x) {
28
+ view.setMixX(x);
29
+ }
30
+
31
+ @ReactProp(name = "y", defaultFloat = 0f)
32
+ public void setY(MixerView view, float y) {
33
+ view.setMixY(y);
34
+ }
35
+
36
+ @ReactProp(name = "width", defaultFloat = 0f)
37
+ public void setWidth(MixerView view, float width) {
38
+ view.setMixWidth(width);
39
+ }
40
+
41
+ @ReactProp(name = "height", defaultFloat = 0f)
42
+ public void setHeight(MixerView view, float height) {
43
+ view.setMixHeight(height);
44
+ }
45
+
46
+ @ReactProp(name = "zOrder", defaultInt = 0)
47
+ public void setZOrder(MixerView view, int zOrder) {
48
+ view.setMixZOrder(zOrder);
49
+ }
50
+
51
+ @ReactProp(name = "renderMode", defaultInt = 0)
52
+ public void setRenderMode(MixerView view, int renderMode) {
53
+ view.setMixRenderMode(renderMode);
54
+ }
55
+
56
+ @ReactProp(name = "captureMode")
57
+ public void setCaptureMode(MixerView view, @Nullable String captureMode) {
58
+ view.setCaptureMode(captureMode != null ? captureMode : "onchange");
59
+ }
60
+
61
+ @ReactProp(name = "captureFramerate", defaultFloat = 30f)
62
+ public void setCaptureFramerate(MixerView view, float framerate) {
63
+ view.setCaptureFramerate(framerate);
64
+ }
65
+
66
+ @ReactProp(name = "autoSensitivity", defaultFloat = 5f)
67
+ public void setAutoSensitivity(MixerView view, float sensitivity) {
68
+ view.setAutoSensitivity(sensitivity);
69
+ }
70
+
71
+ @ReactProp(name = "viewId")
72
+ public void setViewId(MixerView view, @Nullable String viewId) {
73
+ if (viewId != null) {
74
+ view.setViewId(viewId);
75
+ }
76
+ }
77
+ }
78
+
79
+
@@ -0,0 +1,168 @@
1
+ package com.volcengine.velive.rn.push.mixer;
2
+
3
+ import android.graphics.Bitmap;
4
+ import android.opengl.GLES20;
5
+ import android.opengl.GLUtils;
6
+
7
+ import com.pandora.common.env.Env;
8
+ import com.ss.avframework.opengl.GLThreadManager;
9
+ import com.ss.avframework.opengl.GlUtil;
10
+
11
+ import java.nio.ByteBuffer;
12
+
13
+ public class TextureMgr {
14
+ private int texture;
15
+ private int width;
16
+ private int height;
17
+ public TextureMgr(int width, int height) {
18
+ this.width = width;
19
+ this.height = height;
20
+ GLThreadManager.getMainGlHandle().post(() -> {
21
+ if (texture <= 0) {
22
+ texture = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D);
23
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
24
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
25
+ GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
26
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
27
+ GLES20.glFinish();
28
+ GlUtil.checkNoGLES2Error("clearBackgroundTex");
29
+ }
30
+ });
31
+ }
32
+
33
+ public void cleanup() {
34
+ GLThreadManager.getMainGlHandle().post(() -> {
35
+ if (texture > 0) {
36
+ GLES20.glDeleteTextures(1, new int[]{texture}, 0);
37
+ texture = 0;
38
+ }
39
+ });
40
+ }
41
+
42
+ public interface RenderListener {
43
+ void doBusiness(int texture);
44
+ }
45
+
46
+ public void dealWithTexture(ByteBuffer byteBuffer, RenderListener listener) {
47
+ GLThreadManager.getMainGlHandle().post(new Runnable() {
48
+ @Override
49
+ public void run() {
50
+ if (texture > 0) {
51
+ YuvHelper.NV21ToBitmap bm = null;
52
+ Bitmap bmp = null;
53
+ Bitmap rotatedBmp = null;
54
+ try {
55
+ bm = new YuvHelper.NV21ToBitmap(Env.getApplicationContext());
56
+ bmp = bm.nv21ToBitmap(byteBuffer.array(), width, height);
57
+
58
+ if (bmp == null || bmp.isRecycled()) {
59
+ return;
60
+ }
61
+
62
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
63
+ rotatedBmp = YuvHelper.rotateBitmap(bmp, 0, false, true);
64
+
65
+ if (rotatedBmp != null && !rotatedBmp.isRecycled()) {
66
+ GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, rotatedBmp, 0);
67
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
68
+ GLES20.glFlush();
69
+ listener.doBusiness(texture);
70
+ } else {
71
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
72
+ }
73
+ } catch (OutOfMemoryError e) {
74
+ System.gc();
75
+ } catch (Exception e) {
76
+ // Ignore
77
+ } finally {
78
+ if (bmp != null && !bmp.isRecycled()) {
79
+ bmp.recycle();
80
+ }
81
+ if (rotatedBmp != null && rotatedBmp != bmp && !rotatedBmp.isRecycled()) {
82
+ rotatedBmp.recycle();
83
+ }
84
+ if (bm != null) {
85
+ bm.cleanup();
86
+ }
87
+ }
88
+ }
89
+ }
90
+ });
91
+ }
92
+
93
+ public void dealI420WithTexture(ByteBuffer byteBuffer, RenderListener listener) {
94
+ GLThreadManager.getMainGlHandle().post(new Runnable() {
95
+ @Override
96
+ public void run() {
97
+ if (texture > 0) {
98
+ Bitmap bm = null;
99
+ Bitmap rotatedBm = null;
100
+ try {
101
+ bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
102
+ bm.copyPixelsFromBuffer(byteBuffer);
103
+
104
+ if (bm.isRecycled()) {
105
+ return;
106
+ }
107
+
108
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
109
+ rotatedBm = YuvHelper.rotateBitmap(bm, 0, false, true);
110
+
111
+ if (rotatedBm != null && !rotatedBm.isRecycled()) {
112
+ GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, rotatedBm, 0);
113
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
114
+ GLES20.glFlush();
115
+ listener.doBusiness(texture);
116
+ } else {
117
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
118
+ }
119
+ } catch (OutOfMemoryError e) {
120
+ System.gc();
121
+ } catch (Exception e) {
122
+ // Ignore
123
+ } finally {
124
+ if (bm != null && !bm.isRecycled()) {
125
+ bm.recycle();
126
+ }
127
+ if (rotatedBm != null && rotatedBm != bm && !rotatedBm.isRecycled()) {
128
+ rotatedBm.recycle();
129
+ }
130
+ }
131
+ }
132
+ }
133
+ });
134
+ }
135
+
136
+ public void dealWithTexture(Bitmap bitmap, RenderListener listener) {
137
+ GLThreadManager.getMainGlHandle().post(() -> {
138
+ if (texture > 0) {
139
+ Bitmap processedBitmap = null;
140
+ try {
141
+ if (bitmap == null || bitmap.isRecycled()) {
142
+ return;
143
+ }
144
+
145
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
146
+ processedBitmap = YuvHelper.rotateBitmap(bitmap, 0, false, true);
147
+
148
+ if (processedBitmap != null && !processedBitmap.isRecycled()) {
149
+ GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, processedBitmap, 0);
150
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
151
+ GLES20.glFlush();
152
+ listener.doBusiness(texture);
153
+ } else {
154
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
155
+ }
156
+ } catch (OutOfMemoryError e) {
157
+ System.gc();
158
+ } catch (Exception e) {
159
+ // Ignore
160
+ } finally {
161
+ if (processedBitmap != null && processedBitmap != bitmap && !processedBitmap.isRecycled()) {
162
+ processedBitmap.recycle();
163
+ }
164
+ }
165
+ }
166
+ });
167
+ }
168
+ }