@volcengine/react-native-live-push 1.1.3-rc.0 → 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.
Files changed (139) hide show
  1. package/android/build.gradle +2 -2
  2. package/android/src/main/java/com/volcengine/velive/rn/push/ClassHelper.java +9 -0
  3. package/android/src/main/java/com/volcengine/velive/rn/push/NativeVariableManager.java +5 -8
  4. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushModule.java +14 -2
  5. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushPackage.java +16 -13
  6. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushView.java +16 -0
  7. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushViewManager.java +7 -2
  8. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerManager.java +410 -0
  9. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerView.java +434 -0
  10. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerViewManager.java +79 -0
  11. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/TextureMgr.java +168 -0
  12. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/YuvHelper.java +165 -0
  13. package/ios/VeLiveMixerHelper.h +46 -0
  14. package/ios/VeLiveMixerHelper.m +620 -0
  15. package/ios/VeLiveMixerView.h +69 -0
  16. package/ios/VeLiveMixerView.m +600 -0
  17. package/ios/VeLiveMixerViewManager.m +92 -0
  18. package/lib/commonjs/index.js +22698 -20359
  19. package/lib/commonjs/typescript/android/index.d.ts +44 -0
  20. package/lib/commonjs/typescript/codegen/android/api.d.ts +1068 -0
  21. package/lib/commonjs/typescript/codegen/android/callback.d.ts +333 -0
  22. package/lib/commonjs/typescript/codegen/android/errorcode.d.ts +92 -0
  23. package/lib/commonjs/typescript/codegen/android/index.d.ts +5 -0
  24. package/lib/commonjs/typescript/codegen/android/keytype.d.ts +1693 -0
  25. package/lib/commonjs/typescript/codegen/android/types.d.ts +33 -0
  26. package/lib/commonjs/typescript/codegen/ios/api.d.ts +1125 -0
  27. package/lib/commonjs/typescript/codegen/ios/callback.d.ts +242 -0
  28. package/lib/commonjs/typescript/codegen/ios/errorcode.d.ts +154 -0
  29. package/lib/commonjs/typescript/codegen/ios/external.d.ts +1 -0
  30. package/lib/commonjs/typescript/codegen/ios/index.d.ts +6 -0
  31. package/lib/commonjs/typescript/codegen/ios/keytype.d.ts +1154 -0
  32. package/lib/commonjs/typescript/codegen/ios/types.d.ts +46 -0
  33. package/lib/commonjs/typescript/codegen/pack/api.d.ts +1470 -0
  34. package/lib/commonjs/typescript/codegen/pack/callback.d.ts +446 -0
  35. package/lib/commonjs/typescript/codegen/pack/errorcode.d.ts +109 -0
  36. package/lib/commonjs/typescript/codegen/pack/index.d.ts +5 -0
  37. package/lib/commonjs/typescript/codegen/pack/keytype.d.ts +2248 -0
  38. package/lib/commonjs/typescript/codegen/pack/types.d.ts +68 -0
  39. package/lib/commonjs/typescript/codegen/type-shim.d.ts +6 -0
  40. package/lib/commonjs/typescript/component.d.ts +15 -0
  41. package/lib/commonjs/typescript/core/api.d.ts +18 -0
  42. package/lib/commonjs/typescript/core/callback.d.ts +2 -0
  43. package/lib/commonjs/typescript/core/env.d.ts +29 -0
  44. package/lib/commonjs/typescript/core/errorcode.d.ts +2 -0
  45. package/lib/commonjs/typescript/core/index.d.ts +6 -0
  46. package/lib/commonjs/typescript/core/keytype.d.ts +18 -0
  47. package/lib/commonjs/typescript/core/mixer.d.ts +26 -0
  48. package/lib/commonjs/typescript/core/pusher.d.ts +13 -0
  49. package/lib/commonjs/typescript/index.d.ts +3 -0
  50. package/lib/commonjs/typescript/ios/extends.d.ts +41 -0
  51. package/lib/commonjs/typescript/platforms/android/extends.d.ts +8 -0
  52. package/lib/commonjs/typescript/platforms/android/helper.d.ts +8 -0
  53. package/lib/commonjs/typescript/platforms/android/mixer.d.ts +8 -0
  54. package/lib/commonjs/typescript/platforms/ios/extends.d.ts +17 -0
  55. package/lib/commonjs/typescript/platforms/ios/helper.d.ts +8 -0
  56. package/lib/commonjs/typescript/platforms/ios/mixer.d.ts +9 -0
  57. package/lib/commonjs/typescript/runtime.d.ts +1 -0
  58. package/lib/commonjs/typescript/view/MixView.d.ts +52 -0
  59. package/lib/commonjs/typescript/view/VeImageView.d.ts +19 -0
  60. package/lib/commonjs/typescript/view/VeTextView.d.ts +7 -0
  61. package/lib/commonjs/typescript/view/VeView.d.ts +7 -0
  62. package/lib/commonjs/typescript/view/VeWebView.d.ts +7 -0
  63. package/lib/commonjs/typescript/view/index.d.ts +5 -0
  64. package/lib/module/index.js +22695 -20360
  65. package/lib/module/typescript/android/index.d.ts +44 -0
  66. package/lib/module/typescript/codegen/android/api.d.ts +1068 -0
  67. package/lib/module/typescript/codegen/android/callback.d.ts +333 -0
  68. package/lib/module/typescript/codegen/android/errorcode.d.ts +92 -0
  69. package/lib/module/typescript/codegen/android/index.d.ts +5 -0
  70. package/lib/module/typescript/codegen/android/keytype.d.ts +1693 -0
  71. package/lib/module/typescript/codegen/android/types.d.ts +33 -0
  72. package/lib/module/typescript/codegen/ios/api.d.ts +1125 -0
  73. package/lib/module/typescript/codegen/ios/callback.d.ts +242 -0
  74. package/lib/module/typescript/codegen/ios/errorcode.d.ts +154 -0
  75. package/lib/module/typescript/codegen/ios/external.d.ts +1 -0
  76. package/lib/module/typescript/codegen/ios/index.d.ts +6 -0
  77. package/lib/module/typescript/codegen/ios/keytype.d.ts +1154 -0
  78. package/lib/module/typescript/codegen/ios/types.d.ts +46 -0
  79. package/lib/module/typescript/codegen/pack/api.d.ts +1470 -0
  80. package/lib/module/typescript/codegen/pack/callback.d.ts +446 -0
  81. package/lib/module/typescript/codegen/pack/errorcode.d.ts +109 -0
  82. package/lib/module/typescript/codegen/pack/index.d.ts +5 -0
  83. package/lib/module/typescript/codegen/pack/keytype.d.ts +2248 -0
  84. package/lib/module/typescript/codegen/pack/types.d.ts +68 -0
  85. package/lib/module/typescript/codegen/type-shim.d.ts +6 -0
  86. package/lib/module/typescript/component.d.ts +15 -0
  87. package/lib/module/typescript/core/api.d.ts +18 -0
  88. package/lib/module/typescript/core/callback.d.ts +2 -0
  89. package/lib/module/typescript/core/env.d.ts +29 -0
  90. package/lib/module/typescript/core/errorcode.d.ts +2 -0
  91. package/lib/module/typescript/core/index.d.ts +6 -0
  92. package/lib/module/typescript/core/keytype.d.ts +18 -0
  93. package/lib/module/typescript/core/mixer.d.ts +26 -0
  94. package/lib/module/typescript/core/pusher.d.ts +13 -0
  95. package/lib/module/typescript/index.d.ts +3 -0
  96. package/lib/module/typescript/ios/extends.d.ts +41 -0
  97. package/lib/module/typescript/platforms/android/extends.d.ts +8 -0
  98. package/lib/module/typescript/platforms/android/helper.d.ts +8 -0
  99. package/lib/module/typescript/platforms/android/mixer.d.ts +8 -0
  100. package/lib/module/typescript/platforms/ios/extends.d.ts +17 -0
  101. package/lib/module/typescript/platforms/ios/helper.d.ts +8 -0
  102. package/lib/module/typescript/platforms/ios/mixer.d.ts +9 -0
  103. package/lib/module/typescript/runtime.d.ts +1 -0
  104. package/lib/module/typescript/view/MixView.d.ts +52 -0
  105. package/lib/module/typescript/view/VeImageView.d.ts +19 -0
  106. package/lib/module/typescript/view/VeTextView.d.ts +7 -0
  107. package/lib/module/typescript/view/VeView.d.ts +7 -0
  108. package/lib/module/typescript/view/VeWebView.d.ts +7 -0
  109. package/lib/module/typescript/view/index.d.ts +5 -0
  110. package/lib/typescript/android/index.d.ts +0 -3
  111. package/lib/typescript/codegen/android/api.d.ts +194 -762
  112. package/lib/typescript/codegen/android/callback.d.ts +85 -48
  113. package/lib/typescript/codegen/android/errorcode.d.ts +30 -0
  114. package/lib/typescript/codegen/android/keytype.d.ts +514 -122
  115. package/lib/typescript/codegen/ios/api.d.ts +380 -351
  116. package/lib/typescript/codegen/ios/callback.d.ts +33 -6
  117. package/lib/typescript/codegen/ios/errorcode.d.ts +52 -2
  118. package/lib/typescript/codegen/ios/keytype.d.ts +313 -35
  119. package/lib/typescript/codegen/pack/api.d.ts +302 -821
  120. package/lib/typescript/codegen/pack/callback.d.ts +54 -49
  121. package/lib/typescript/codegen/pack/errorcode.d.ts +38 -5
  122. package/lib/typescript/codegen/pack/keytype.d.ts +672 -228
  123. package/lib/typescript/core/api.d.ts +18 -2
  124. package/lib/typescript/core/keytype.d.ts +16 -0
  125. package/lib/typescript/core/mixer.d.ts +26 -0
  126. package/lib/typescript/core/pusher.d.ts +0 -3
  127. package/lib/typescript/index.d.ts +1 -0
  128. package/lib/typescript/platforms/android/extends.d.ts +8 -0
  129. package/lib/typescript/platforms/android/mixer.d.ts +8 -0
  130. package/lib/typescript/platforms/ios/mixer.d.ts +9 -0
  131. package/lib/typescript/view/MixView.d.ts +52 -0
  132. package/lib/typescript/view/VeImageView.d.ts +19 -0
  133. package/lib/typescript/view/VeTextView.d.ts +7 -0
  134. package/lib/typescript/view/VeView.d.ts +7 -0
  135. package/lib/typescript/view/VeWebView.d.ts +7 -0
  136. package/lib/typescript/view/index.d.ts +5 -0
  137. package/package.json +1 -1
  138. package/react-native-velive-push.podspec +3 -3
  139. package/android/src/main/java/com/volcengine/velive/rn/push/ScreenCaptureHelper.java +0 -73
@@ -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.3"
91
- api 'com.bytedanceapi:ttsdk-ttlivepush_rtc:1.41.3.4'
90
+ implementation "com.volcengine:VolcApiEngine:1.6.2"
91
+ api 'com.bytedanceapi:ttsdk-ttlivepush_rtc:1.46.3.6'
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, ReactApplicationContext reactContext) {
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
- var helper = new ScreenCaptureHelper(reactContext);
16
- m.registerVar("screenIntent", helper::getScreenIntent);
17
- helper.setup();
12
+ m.registerVar("ApplicationContext",
13
+ (Object[] args) -> reactContext.getApplicationContext());
14
+ m.registerVar("ReactApplicationContext", (Object[] args) -> reactContext);
18
15
  }
19
16
  }
@@ -50,6 +50,7 @@ public class VeLivePushModule extends VeLivePushModuleSpec implements IEventRece
50
50
  apiEngine = new VolcApiEngine(getReactApplicationContext(), this);
51
51
 
52
52
  NativeVariableManager.init(apiEngine, super.context);
53
+ ClassHelper.init();
53
54
  return true;
54
55
  }
55
56
 
@@ -82,8 +83,19 @@ public class VeLivePushModule extends VeLivePushModuleSpec implements IEventRece
82
83
  try {
83
84
  newApiEngine();
84
85
  String params = arg.getString("params");
85
- this.apiEngine.callApi(params, (res) -> {
86
- callback.invoke(res.toJsonString());
86
+
87
+ // 获取主线程处理器
88
+ android.os.Handler mainHandler =
89
+ new android.os.Handler(android.os.Looper.getMainLooper());
90
+
91
+ // 在主线程上执行 API 调用
92
+ mainHandler.post(() -> {
93
+ try {
94
+ this.apiEngine.callApi(
95
+ params, (res) -> { callback.invoke(res.toJsonString()); });
96
+ } catch (Exception e) {
97
+ e.printStackTrace();
98
+ }
87
99
  });
88
100
  } catch (Exception e) {
89
101
  e.printStackTrace();
@@ -4,24 +4,27 @@ import com.facebook.react.ReactPackage;
4
4
  import com.facebook.react.bridge.NativeModule;
5
5
  import com.facebook.react.bridge.ReactApplicationContext;
6
6
  import com.facebook.react.uimanager.ViewManager;
7
-
7
+ import com.volcengine.velive.rn.push.mixer.MixerViewManager;
8
8
  import java.util.ArrayList;
9
9
  import java.util.List;
10
10
 
11
11
  public class VeLivePushPackage implements ReactPackage {
12
- @Override
13
- public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
14
- List<ViewManager> viewManagers = new ArrayList<>();
15
- viewManagers.add(new VeLivePushViewManager());
16
- return viewManagers;
17
- }
12
+ @Override
13
+ public List<ViewManager>
14
+ createViewManagers(ReactApplicationContext reactContext) {
15
+ List<ViewManager> viewManagers = new ArrayList<>();
16
+ viewManagers.add(new VeLivePushViewManager());
17
+ viewManagers.add(new MixerViewManager());
18
+ return viewManagers;
19
+ }
18
20
 
19
- @Override
20
- public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
21
- List<NativeModule> modules = new ArrayList<>();
21
+ @Override
22
+ public List<NativeModule>
23
+ createNativeModules(ReactApplicationContext reactContext) {
24
+ List<NativeModule> modules = new ArrayList<>();
22
25
 
23
- modules.add(new VeLivePushModule(reactContext));
26
+ modules.add(new VeLivePushModule(reactContext));
24
27
 
25
- return modules;
26
- }
28
+ return modules;
29
+ }
27
30
  }
@@ -123,4 +123,20 @@ public class VeLivePushView extends FrameLayout {
123
123
  reactContext.getJSModule(RCTEventEmitter.class)
124
124
  .receiveEvent(getId(), "load", event);
125
125
  }
126
+
127
+ @Override
128
+ protected void onAttachedToWindow() {
129
+ super.onAttachedToWindow();
130
+ if (viewId != null && hasRegister) {
131
+ VolcViewManager.putViewById(viewId, this);
132
+ }
133
+ }
134
+
135
+ @Override
136
+ protected void onDetachedFromWindow() {
137
+ super.onDetachedFromWindow();
138
+ if (viewId != null) {
139
+ // VolcViewManager.removeViewById(viewId);
140
+ }
141
+ }
126
142
  }
@@ -3,6 +3,8 @@ package com.volcengine.velive.rn.push;
3
3
  import android.os.Looper;
4
4
  import androidx.annotation.NonNull;
5
5
  import androidx.annotation.Nullable;
6
+
7
+ import com.facebook.react.bridge.ReactApplicationContext;
6
8
  import com.facebook.react.bridge.ReadableArray;
7
9
  import com.facebook.react.common.MapBuilder;
8
10
  import com.facebook.react.uimanager.SimpleViewManager;
@@ -12,8 +14,10 @@ import java.util.Map;
12
14
 
13
15
  public class VeLivePushViewManager extends SimpleViewManager<VeLivePushView> {
14
16
  public static final String NAME = "VeLivePushView";
15
-
16
- private ThemedReactContext context;
17
+
18
+ public static ReactApplicationContext ctx;
19
+
20
+ public ThemedReactContext context;
17
21
 
18
22
  @NonNull
19
23
  @Override
@@ -31,6 +35,7 @@ public class VeLivePushViewManager extends SimpleViewManager<VeLivePushView> {
31
35
  "View must be created on the main thread");
32
36
  }
33
37
  context = reactContext;
38
+ ctx = context.getReactApplicationContext();
34
39
  return new VeLivePushView(reactContext);
35
40
  }
36
41
 
@@ -0,0 +1,410 @@
1
+ package com.volcengine.velive.rn.push.mixer;
2
+
3
+ import android.graphics.Bitmap;
4
+ import android.util.Log;
5
+ import android.view.View;
6
+ import android.view.ViewTreeObserver;
7
+ import com.ss.avframework.live.VeLivePusher;
8
+ import com.ss.avframework.live.VeLivePusherDef.VeLiveMixVideoLayout;
9
+ import com.ss.avframework.live.VeLivePusherDef.VeLivePusherRenderMode;
10
+ import com.ss.avframework.live.VeLivePusherDef.VeLiveStreamMixDescription;
11
+ import com.ss.avframework.live.VeLiveVideoFrame;
12
+ import java.util.HashMap;
13
+ import java.util.Map;
14
+ import java.util.concurrent.ConcurrentHashMap;
15
+ import javax.annotation.Nullable;
16
+ import org.json.JSONObject;
17
+
18
+ public class MixerManager {
19
+ public static Map<String, View> cachedMixedViews = new HashMap<>();
20
+
21
+ private static final String TAG = "MixerManager";
22
+
23
+ private VeLivePusher pusher;
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; }
32
+
33
+ /**
34
+ * Add a view to the mixer
35
+ * @param viewId Unique identifier for the view
36
+ * @param viewInfo Configuration for the view
37
+ * @return streamId for this view
38
+ */
39
+ public int addView(String viewId, JSONObject viewInfo) {
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
+ }
96
+ }
97
+
98
+ /**
99
+ * Update view configuration
100
+ */
101
+ public boolean updateView(String viewId, JSONObject viewInfo) {
102
+ try {
103
+ VeLiveMixVideoLayout layout = mixedViewLayout.get(viewId);
104
+ if (layout == null) {
105
+ return false;
106
+ }
107
+ VeLiveStreamMixDescription description = new VeLiveStreamMixDescription();
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);
113
+ Integer streamId = viewIdToStreamId.get(viewId);
114
+ if (streamId != null) {
115
+ layout.streamId = streamId;
116
+ }
117
+ if (viewInfo.has("zOrder")) {
118
+ layout.zOrder = viewInfo.getInt("zOrder");
119
+ }
120
+ if (viewInfo.has("renderMode")) {
121
+ int renderModeValue = viewInfo.getInt("renderMode");
122
+ VeLivePusherRenderMode[] renderModes = VeLivePusherRenderMode.values();
123
+ if (renderModeValue >= 0 && renderModeValue < renderModes.length) {
124
+ layout.renderMode = renderModes[renderModeValue];
125
+ }
126
+ }
127
+ mixedViewLayout.put(viewId, layout);
128
+ description.mixVideoStreams.add(layout);
129
+ pusher.getMixerManager().updateStreamMixDescription(description);
130
+
131
+ View view = cachedMixedViews.get(viewId);
132
+ if (view instanceof MixerView) {
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);
146
+ }
147
+ return true;
148
+ } catch (Exception e) {
149
+ return false;
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Remove view from mixer
155
+ */
156
+ public boolean removeView(String viewId) {
157
+ try {
158
+ VeLiveMixVideoLayout layout = mixedViewLayout.remove(viewId);
159
+ if (layout == null) {
160
+ return false;
161
+ }
162
+
163
+ viewIdToStreamId.remove(viewId);
164
+
165
+ View view = cachedMixedViews.get(viewId);
166
+ if (view instanceof MixerView) {
167
+ MixerView mixerView = (MixerView)view;
168
+ mixerView.setBitmapCaptureCallback(null);
169
+ }
170
+ cachedMixedViews.remove(viewId);
171
+
172
+ pusher.getMixerManager().removeVideoStream(layout.streamId);
173
+ return true;
174
+
175
+ } catch (Exception e) {
176
+ return false;
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Manually trigger bitmap capture for a view
182
+ */
183
+ public void captureView(String viewId) {
184
+ View view = cachedMixedViews.get(viewId);
185
+ if (view instanceof MixerView) {
186
+ MixerView mixerView = (MixerView)view;
187
+ mixerView.performManualCapture();
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Called when MixerView is ready - check for pending callbacks
193
+ */
194
+ public static void onViewReady(String viewId, MixerView mixerView) {
195
+ try {
196
+ MixerManager instance = findActiveMixerManager();
197
+ if (instance != null) {
198
+ Integer streamId = instance.pendingCallbacks.remove(viewId);
199
+ if (streamId != null) {
200
+ setupCallbackForMixerView(mixerView, streamId);
201
+
202
+ android.os.Handler mainHandler =
203
+ new android.os.Handler(android.os.Looper.getMainLooper());
204
+ mainHandler.postDelayed(new Runnable() {
205
+ @Override
206
+ public void run() {
207
+ try {
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();
214
+ description.mixVideoStreams.add(layout);
215
+ instance.pusher.getMixerManager().updateStreamMixDescription(
216
+ description);
217
+ }
218
+ mixerView.performManualCapture();
219
+ } catch (Exception e) {
220
+ Log.w(TAG, "Failed to perform operations in onViewReady", e);
221
+ }
222
+ }
223
+ }, 300);
224
+ }
225
+ }
226
+ } catch (Exception e) {
227
+ Log.w(TAG, "Error in onViewReady", e);
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Send captured bitmap to mixer as video frame
233
+ */
234
+ private void sendBitmapToMixer(int streamId, Bitmap bitmap) {
235
+ try {
236
+ if (bitmap == null || bitmap.isRecycled()) {
237
+ return;
238
+ }
239
+
240
+ if (pusher == null || pusher.getMixerManager() == null) {
241
+ return;
242
+ }
243
+
244
+ int width = bitmap.getWidth();
245
+ int height = bitmap.getHeight();
246
+
247
+ if (width <= 0 || height <= 0) {
248
+ return;
249
+ }
250
+
251
+ TextureMgr textureMgr = new TextureMgr(width, height);
252
+ textureMgr.dealWithTexture(bitmap, new TextureMgr.RenderListener() {
253
+ @Override
254
+ public void doBusiness(int texture) {
255
+ try {
256
+ if (texture <= 0) {
257
+ return;
258
+ }
259
+
260
+ long pts = System.currentTimeMillis() * 1000;
261
+ VeLiveVideoFrame videoFrame =
262
+ new VeLiveVideoFrame(width, height, pts, texture, false, null);
263
+
264
+ if (pusher != null && pusher.getMixerManager() != null) {
265
+ pusher.getMixerManager().sendCustomVideoFrame(videoFrame,
266
+ streamId);
267
+ }
268
+ } catch (Exception e) {
269
+ // Ignore
270
+ } finally {
271
+ textureMgr.cleanup();
272
+ }
273
+ }
274
+ });
275
+ } catch (Exception e) {
276
+ // Ignore
277
+ }
278
+ }
279
+
280
+ /**
281
+ * Static method to set up callback for MixerView
282
+ * Now with intelligent layout waiting logic
283
+ */
284
+ private static void setupCallbackForMixerView(MixerView mixerView,
285
+ int streamId) {
286
+ if (mixerView == null) {
287
+ return;
288
+ }
289
+
290
+ mixerView.setBitmapCaptureCallback(new BitmapCaptureCallback() {
291
+ @Override
292
+ public void onBitmapCaptured(Bitmap bitmap) {
293
+ try {
294
+ if (bitmap != null && !bitmap.isRecycled()) {
295
+ sendBitmapToMixerStatic(streamId, bitmap);
296
+ }
297
+ } catch (OutOfMemoryError e) {
298
+ System.gc();
299
+ } catch (Exception e) {
300
+ // Ignore
301
+ }
302
+ }
303
+
304
+ @Override
305
+ public void onCaptureError(String error) {
306
+ // Ignore
307
+ }
308
+ });
309
+
310
+ if (mixerView.getWidth() > 0 && mixerView.getHeight() > 0) {
311
+ try {
312
+ mixerView.performManualCapture();
313
+ } catch (Exception e) {
314
+ // Ignore
315
+ }
316
+ } else {
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
331
+ }
332
+ }
333
+ };
334
+
335
+ try {
336
+ mixerView.getViewTreeObserver().addOnGlobalLayoutListener(
337
+ layoutListener);
338
+ } catch (Exception e) {
339
+ // Ignore
340
+ }
341
+ }
342
+ }
343
+
344
+ /**
345
+ * Static version of sendBitmapToMixer - finds the active MixerManager
346
+ * instance
347
+ */
348
+ private static void sendBitmapToMixerStatic(int streamId, Bitmap bitmap) {
349
+ try {
350
+ MixerManager instance = findActiveMixerManager();
351
+ if (instance != null && instance.pusher != null) {
352
+ instance.sendBitmapToMixer(streamId, bitmap);
353
+ }
354
+ } catch (Exception e) {
355
+ // Ignore
356
+ }
357
+ }
358
+
359
+ /**
360
+ * Find the active MixerManager instance
361
+ */
362
+ private static MixerManager findActiveMixerManager() {
363
+ MixerManager instance = currentInstance;
364
+ if (instance != null && instance.pusher != null) {
365
+ return instance;
366
+ }
367
+ return null;
368
+ }
369
+
370
+ private static volatile MixerManager currentInstance;
371
+
372
+ public MixerManager() {
373
+ synchronized (MixerManager.class) { currentInstance = this; }
374
+ }
375
+
376
+ /**
377
+ * cleanup method to release resources
378
+ */
379
+ public void cleanup() {
380
+ try {
381
+ for (String viewId : cachedMixedViews.keySet()) {
382
+ View view = cachedMixedViews.get(viewId);
383
+ if (view instanceof MixerView) {
384
+ MixerView mixerView = (MixerView)view;
385
+ mixerView.setBitmapCaptureCallback(null);
386
+ }
387
+ }
388
+
389
+ mixedViewLayout.clear();
390
+ viewIdToStreamId.clear();
391
+ pendingCallbacks.clear();
392
+
393
+ synchronized (MixerManager.class) {
394
+ if (currentInstance == this) {
395
+ currentInstance = null;
396
+ }
397
+ }
398
+
399
+ pusher = null;
400
+ } catch (Exception e) {
401
+ // Ignore
402
+ }
403
+ }
404
+
405
+ // Callback interface for bitmap capture
406
+ public interface BitmapCaptureCallback {
407
+ void onBitmapCaptured(Bitmap bitmap);
408
+ void onCaptureError(String error);
409
+ }
410
+ }