@byteplus/react-native-live-push 1.1.3-rc.4 → 1.1.4-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 (123) hide show
  1. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushModule.java +2 -13
  2. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushPackage.java +13 -16
  3. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushView.java +0 -16
  4. package/android/src/main/java/com/volcengine/velive/rn/push/VeLivePushViewManager.java +2 -7
  5. package/lib/commonjs/index.js +1027 -466
  6. package/lib/module/index.js +1029 -463
  7. package/lib/typescript/codegen/android/api.d.ts +121 -1
  8. package/lib/typescript/codegen/ios/api.d.ts +28 -1
  9. package/lib/typescript/codegen/pack/api.d.ts +133 -1
  10. package/lib/typescript/core/api.d.ts +2 -17
  11. package/lib/typescript/core/keytype.d.ts +0 -16
  12. package/lib/typescript/index.d.ts +0 -1
  13. package/package.json +1 -1
  14. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerManager.java +0 -412
  15. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerView.java +0 -423
  16. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerViewManager.java +0 -79
  17. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/TextureMgr.java +0 -168
  18. package/android/src/main/java/com/volcengine/velive/rn/push/mixer/YuvHelper.java +0 -165
  19. package/ios/VeLiveMixerHelper.h +0 -44
  20. package/ios/VeLiveMixerHelper.m +0 -620
  21. package/ios/VeLiveMixerView.h +0 -69
  22. package/ios/VeLiveMixerView.m +0 -600
  23. package/ios/VeLiveMixerViewManager.m +0 -92
  24. package/lib/commonjs/typescript/android/index.d.ts +0 -47
  25. package/lib/commonjs/typescript/codegen/android/api.d.ts +0 -1527
  26. package/lib/commonjs/typescript/codegen/android/callback.d.ts +0 -91
  27. package/lib/commonjs/typescript/codegen/android/errorcode.d.ts +0 -26
  28. package/lib/commonjs/typescript/codegen/android/index.d.ts +0 -5
  29. package/lib/commonjs/typescript/codegen/android/keytype.d.ts +0 -846
  30. package/lib/commonjs/typescript/codegen/android/types.d.ts +0 -33
  31. package/lib/commonjs/typescript/codegen/ios/api.d.ts +0 -222
  32. package/lib/commonjs/typescript/codegen/ios/callback.d.ts +0 -80
  33. package/lib/commonjs/typescript/codegen/ios/errorcode.d.ts +0 -54
  34. package/lib/commonjs/typescript/codegen/ios/external.d.ts +0 -1
  35. package/lib/commonjs/typescript/codegen/ios/index.d.ts +0 -6
  36. package/lib/commonjs/typescript/codegen/ios/keytype.d.ts +0 -460
  37. package/lib/commonjs/typescript/codegen/ios/types.d.ts +0 -46
  38. package/lib/commonjs/typescript/codegen/pack/api.d.ts +0 -1835
  39. package/lib/commonjs/typescript/codegen/pack/callback.d.ts +0 -400
  40. package/lib/commonjs/typescript/codegen/pack/errorcode.d.ts +0 -35
  41. package/lib/commonjs/typescript/codegen/pack/index.d.ts +0 -5
  42. package/lib/commonjs/typescript/codegen/pack/keytype.d.ts +0 -1392
  43. package/lib/commonjs/typescript/codegen/pack/types.d.ts +0 -68
  44. package/lib/commonjs/typescript/codegen/type-shim.d.ts +0 -6
  45. package/lib/commonjs/typescript/component.d.ts +0 -15
  46. package/lib/commonjs/typescript/core/api.d.ts +0 -17
  47. package/lib/commonjs/typescript/core/callback.d.ts +0 -2
  48. package/lib/commonjs/typescript/core/env.d.ts +0 -29
  49. package/lib/commonjs/typescript/core/errorcode.d.ts +0 -2
  50. package/lib/commonjs/typescript/core/index.d.ts +0 -6
  51. package/lib/commonjs/typescript/core/keytype.d.ts +0 -18
  52. package/lib/commonjs/typescript/core/mixer.d.ts +0 -26
  53. package/lib/commonjs/typescript/core/pusher.d.ts +0 -16
  54. package/lib/commonjs/typescript/index.d.ts +0 -3
  55. package/lib/commonjs/typescript/ios/extends.d.ts +0 -41
  56. package/lib/commonjs/typescript/platforms/android/extends.d.ts +0 -8
  57. package/lib/commonjs/typescript/platforms/android/helper.d.ts +0 -8
  58. package/lib/commonjs/typescript/platforms/android/mixer.d.ts +0 -8
  59. package/lib/commonjs/typescript/platforms/ios/extends.d.ts +0 -17
  60. package/lib/commonjs/typescript/platforms/ios/helper.d.ts +0 -8
  61. package/lib/commonjs/typescript/platforms/ios/mixer.d.ts +0 -9
  62. package/lib/commonjs/typescript/runtime.d.ts +0 -1
  63. package/lib/commonjs/typescript/view/MixView.d.ts +0 -52
  64. package/lib/commonjs/typescript/view/VeImageView.d.ts +0 -19
  65. package/lib/commonjs/typescript/view/VeTextView.d.ts +0 -7
  66. package/lib/commonjs/typescript/view/VeView.d.ts +0 -7
  67. package/lib/commonjs/typescript/view/VeWebView.d.ts +0 -7
  68. package/lib/commonjs/typescript/view/index.d.ts +0 -5
  69. package/lib/module/typescript/android/index.d.ts +0 -47
  70. package/lib/module/typescript/codegen/android/api.d.ts +0 -1527
  71. package/lib/module/typescript/codegen/android/callback.d.ts +0 -91
  72. package/lib/module/typescript/codegen/android/errorcode.d.ts +0 -26
  73. package/lib/module/typescript/codegen/android/index.d.ts +0 -5
  74. package/lib/module/typescript/codegen/android/keytype.d.ts +0 -846
  75. package/lib/module/typescript/codegen/android/types.d.ts +0 -33
  76. package/lib/module/typescript/codegen/ios/api.d.ts +0 -222
  77. package/lib/module/typescript/codegen/ios/callback.d.ts +0 -80
  78. package/lib/module/typescript/codegen/ios/errorcode.d.ts +0 -54
  79. package/lib/module/typescript/codegen/ios/external.d.ts +0 -1
  80. package/lib/module/typescript/codegen/ios/index.d.ts +0 -6
  81. package/lib/module/typescript/codegen/ios/keytype.d.ts +0 -460
  82. package/lib/module/typescript/codegen/ios/types.d.ts +0 -46
  83. package/lib/module/typescript/codegen/pack/api.d.ts +0 -1835
  84. package/lib/module/typescript/codegen/pack/callback.d.ts +0 -400
  85. package/lib/module/typescript/codegen/pack/errorcode.d.ts +0 -35
  86. package/lib/module/typescript/codegen/pack/index.d.ts +0 -5
  87. package/lib/module/typescript/codegen/pack/keytype.d.ts +0 -1392
  88. package/lib/module/typescript/codegen/pack/types.d.ts +0 -68
  89. package/lib/module/typescript/codegen/type-shim.d.ts +0 -6
  90. package/lib/module/typescript/component.d.ts +0 -15
  91. package/lib/module/typescript/core/api.d.ts +0 -17
  92. package/lib/module/typescript/core/callback.d.ts +0 -2
  93. package/lib/module/typescript/core/env.d.ts +0 -29
  94. package/lib/module/typescript/core/errorcode.d.ts +0 -2
  95. package/lib/module/typescript/core/index.d.ts +0 -6
  96. package/lib/module/typescript/core/keytype.d.ts +0 -18
  97. package/lib/module/typescript/core/mixer.d.ts +0 -26
  98. package/lib/module/typescript/core/pusher.d.ts +0 -16
  99. package/lib/module/typescript/index.d.ts +0 -3
  100. package/lib/module/typescript/ios/extends.d.ts +0 -41
  101. package/lib/module/typescript/platforms/android/extends.d.ts +0 -8
  102. package/lib/module/typescript/platforms/android/helper.d.ts +0 -8
  103. package/lib/module/typescript/platforms/android/mixer.d.ts +0 -8
  104. package/lib/module/typescript/platforms/ios/extends.d.ts +0 -17
  105. package/lib/module/typescript/platforms/ios/helper.d.ts +0 -8
  106. package/lib/module/typescript/platforms/ios/mixer.d.ts +0 -9
  107. package/lib/module/typescript/runtime.d.ts +0 -1
  108. package/lib/module/typescript/view/MixView.d.ts +0 -52
  109. package/lib/module/typescript/view/VeImageView.d.ts +0 -19
  110. package/lib/module/typescript/view/VeTextView.d.ts +0 -7
  111. package/lib/module/typescript/view/VeView.d.ts +0 -7
  112. package/lib/module/typescript/view/VeWebView.d.ts +0 -7
  113. package/lib/module/typescript/view/index.d.ts +0 -5
  114. package/lib/typescript/core/mixer.d.ts +0 -26
  115. package/lib/typescript/platforms/android/extends.d.ts +0 -8
  116. package/lib/typescript/platforms/android/mixer.d.ts +0 -8
  117. package/lib/typescript/platforms/ios/mixer.d.ts +0 -9
  118. package/lib/typescript/view/MixView.d.ts +0 -52
  119. package/lib/typescript/view/VeImageView.d.ts +0 -19
  120. package/lib/typescript/view/VeTextView.d.ts +0 -7
  121. package/lib/typescript/view/VeView.d.ts +0 -7
  122. package/lib/typescript/view/VeWebView.d.ts +0 -7
  123. package/lib/typescript/view/index.d.ts +0 -5
@@ -1,600 +0,0 @@
1
- //
2
- // VeLiveMixerView.m
3
- // react-native-live-push
4
- //
5
- // Created by ByteDance on 2024/12/09.
6
- //
7
-
8
- #import "VeLiveMixerView.h"
9
- #import "VeLiveMixerHelper.h"
10
- #import <AVFoundation/AVFoundation.h>
11
- #import <CoreMedia/CoreMedia.h>
12
- #import <CoreVideo/CoreVideo.h>
13
- #import <UIKit/UIKit.h>
14
-
15
- @interface VeLiveMixerUIView ()
16
-
17
- // Mix configuration - Align with Android
18
- @property(nonatomic, assign) float mixX;
19
- @property(nonatomic, assign) float mixY;
20
- @property(nonatomic, assign) float mixWidth;
21
- @property(nonatomic, assign) float mixHeight;
22
- @property(nonatomic, assign) int mixZOrder;
23
- @property(nonatomic, assign) int mixRenderMode;
24
-
25
- // Capture configuration - Internal properties
26
- @property(nonatomic, strong) NSString *internalCaptureMode;
27
- @property(nonatomic, assign) float internalCaptureFramerate;
28
- @property(nonatomic, assign) float internalAutoSensitivity;
29
-
30
- // Capture state - Align with Android
31
- @property(nonatomic, strong) NSTimer *captureTimer;
32
- @property(nonatomic, assign) BOOL isCapturing;
33
- @property(nonatomic, assign) BOOL isDestroyed;
34
- @property(nonatomic, assign) CFTimeInterval lastCaptureTime;
35
-
36
- // Performance optimization - Align with Android
37
- @property(nonatomic, strong) UIImage *lastBitmap;
38
-
39
- // Auto mode state - Align with Android
40
- @property(nonatomic, assign) int changeCount;
41
- @property(nonatomic, assign) CFTimeInterval windowStartTime;
42
- @property(nonatomic, assign) BOOL isInRealtimeMode;
43
-
44
- @end
45
-
46
- @implementation VeLiveMixerUIView
47
-
48
- static const CFTimeInterval AUTO_WINDOW_SECONDS = 2.0; // 2 second window
49
- static const int HIGH_CHANGE_THRESHOLD = 10;
50
- static const int LOW_CHANGE_THRESHOLD = 2;
51
-
52
- - (instancetype)initWithFrame:(CGRect)frame {
53
- self = [super initWithFrame:frame];
54
- if (self) {
55
- [self initializeCapture];
56
- [self setupUIView];
57
- }
58
- return self;
59
- }
60
-
61
- - (void)setupUIView {
62
- // Reference VeLivePushView.m settings, but keep our mixed view features
63
- self.clipsToBounds = YES; // Changed to YES, consistent with VeLivePushView
64
- self.userInteractionEnabled = YES;
65
-
66
- // Set default background color to transparent, allowing subviews to display
67
- self.backgroundColor = [UIColor clearColor];
68
- }
69
-
70
- - (void)initializeCapture {
71
- // Initialize defaults - Completely align with Android
72
- _mixX = 0.0f;
73
- _mixY = 0.0f;
74
- _mixWidth = 0.0f;
75
- _mixHeight = 0.0f;
76
- _mixZOrder = 0;
77
- _mixRenderMode = 0;
78
-
79
- _internalCaptureMode = @"onchange";
80
- _internalCaptureFramerate = 30.0f;
81
- _internalAutoSensitivity = 5.0f;
82
-
83
- _isCapturing = NO;
84
- _isDestroyed = NO;
85
- _lastCaptureTime = 0;
86
-
87
- // Auto mode state
88
- _changeCount = 0;
89
- _windowStartTime = 0;
90
- _isInRealtimeMode = NO;
91
- }
92
-
93
- #pragma mark - Property Getters/Setters - Align with React Native props
94
-
95
- - (NSString *)captureMode {
96
- return self.internalCaptureMode;
97
- }
98
-
99
- - (void)setCaptureMode:(NSString *)mode {
100
- if ([mode isEqualToString:self.internalCaptureMode])
101
- return;
102
-
103
- [self stopCapture];
104
- _internalCaptureMode = mode;
105
- [self startCapture];
106
- }
107
-
108
- - (NSNumber *)captureFramerate {
109
- return @(self.internalCaptureFramerate);
110
- }
111
-
112
- - (void)setCaptureFramerate:(NSNumber *)framerate {
113
- _internalCaptureFramerate = MAX(1.0f, MIN(60.0f, [framerate floatValue]));
114
- if ([self.internalCaptureMode isEqualToString:@"realtime"]) {
115
- [self restartRealtimeCapture];
116
- }
117
- }
118
-
119
- - (NSNumber *)autoSensitivity {
120
- return @(self.internalAutoSensitivity);
121
- }
122
-
123
- - (void)setAutoSensitivity:(NSNumber *)sensitivity {
124
- _internalAutoSensitivity = MAX(1.0f, MIN(10.0f, [sensitivity floatValue]));
125
- }
126
-
127
- - (void)setViewId:(NSString *)viewId {
128
- if (!viewId) {
129
- return;
130
- }
131
-
132
- // Set viewId
133
- _viewId = [viewId copy];
134
-
135
- // Register to global cache - Align with Android's onAttachedToWindow
136
- NSMutableDictionary *cachedViews = [VeLiveMixerHelper cachedMixedViews];
137
- if (cachedViews) {
138
- [cachedViews setObject:self forKey:viewId];
139
-
140
- // Notify MixerHelper view is ready, check for pending callbacks
141
- [VeLiveMixerHelper onViewReady:viewId mixerView:self];
142
- }
143
- }
144
-
145
- #pragma mark - Property setters for React Native props - Align with Android
146
-
147
- // React Native property setter - Corresponds to VeLiveMixerViewManager.m
148
- // properties
149
- - (void)setX:(NSNumber *)x {
150
- _x = x;
151
- _mixX = [x floatValue];
152
- }
153
-
154
- - (void)setY:(NSNumber *)y {
155
- _y = y;
156
- _mixY = [y floatValue];
157
- }
158
-
159
- - (void)setWidth:(NSNumber *)width {
160
- _width = width;
161
- _mixWidth = [width floatValue];
162
- }
163
-
164
- - (void)setHeight:(NSNumber *)height {
165
- _height = height;
166
- _mixHeight = [height floatValue];
167
- }
168
-
169
- - (void)setZOrder:(NSNumber *)zOrder {
170
- _zOrder = zOrder;
171
- _mixZOrder = [zOrder intValue];
172
- }
173
-
174
- - (void)setRenderMode:(NSNumber *)renderMode {
175
- _renderMode = renderMode;
176
- _mixRenderMode = [renderMode intValue];
177
- }
178
-
179
- #pragma mark - Internal setters for mix configuration - Internal use
180
-
181
- - (void)setMixX:(float)x {
182
- _mixX = x;
183
- }
184
- - (void)setMixY:(float)y {
185
- _mixY = y;
186
- }
187
- - (void)setMixWidth:(float)width {
188
- _mixWidth = width;
189
- }
190
- - (void)setMixHeight:(float)height {
191
- _mixHeight = height;
192
- }
193
- - (void)setMixZOrder:(int)zOrder {
194
- _mixZOrder = zOrder;
195
- }
196
- - (void)setMixRenderMode:(int)renderMode {
197
- _mixRenderMode = renderMode;
198
- }
199
-
200
- #pragma mark - Capture Methods - Completely align with Android
201
-
202
- - (void)startCapture {
203
- if (self.isDestroyed)
204
- return;
205
-
206
- if ([self.internalCaptureMode isEqualToString:@"onchange"]) {
207
- [self startOnChangeCapture];
208
- } else if ([self.internalCaptureMode isEqualToString:@"realtime"]) {
209
- [self startRealtimeCapture];
210
- } else if ([self.internalCaptureMode isEqualToString:@"auto"]) {
211
- [self startAutoCapture];
212
- }
213
- // manual mode doesn't auto-start
214
- }
215
-
216
- - (void)stopCapture {
217
- [self.captureTimer invalidate];
218
- self.captureTimer = nil;
219
- self.isCapturing = NO;
220
- }
221
-
222
- - (void)startOnChangeCapture {
223
- // onchange mode triggers in layoutSubviews
224
- }
225
-
226
- - (void)startRealtimeCapture {
227
- long interval = (long)(1000.0f / self.internalCaptureFramerate);
228
- self.captureTimer =
229
- [NSTimer scheduledTimerWithTimeInterval:interval / 1000.0
230
- target:self
231
- selector:@selector(realtimeCapture)
232
- userInfo:nil
233
- repeats:YES];
234
- }
235
-
236
- - (void)realtimeCapture {
237
- if (!self.isDestroyed &&
238
- [self.internalCaptureMode isEqualToString:@"realtime"]) {
239
- @autoreleasepool {
240
- [self performCapture:@"realtime"];
241
-
242
- // Every 5 realtime captures, perform background memory cleanup
243
- static int captureCount = 0;
244
- captureCount++;
245
- if (captureCount % 5 == 0) {
246
- dispatch_async(
247
- dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
248
- [[NSURLCache sharedURLCache] removeAllCachedResponses];
249
- [[NSURLCache sharedURLCache] setMemoryCapacity:0];
250
- [[NSURLCache sharedURLCache]
251
- setMemoryCapacity:10 * 1024 * 1024]; // 10MB
252
- });
253
- }
254
- }
255
- }
256
- }
257
-
258
- - (void)restartRealtimeCapture {
259
- if ([self.internalCaptureMode isEqualToString:@"realtime"]) {
260
- [self stopCapture];
261
- [self startRealtimeCapture];
262
- }
263
- }
264
-
265
- - (void)startAutoCapture {
266
- // Start with onchange mode
267
- self.isInRealtimeMode = NO;
268
- self.windowStartTime = CACurrentMediaTime();
269
- self.changeCount = 0;
270
- [self startOnChangeCapture];
271
- }
272
-
273
- #pragma mark - Layout Change Detection - Align with Android's onViewChanged
274
-
275
- - (void)handleAutoModeChange {
276
- if (!self.isInRealtimeMode) {
277
- [self performCapture:@"auto_onchange"];
278
- }
279
-
280
- // Count changes for auto mode
281
- self.changeCount++;
282
-
283
- CFTimeInterval currentTime = CACurrentMediaTime();
284
- if (currentTime - self.windowStartTime >= AUTO_WINDOW_SECONDS) {
285
- [self evaluateAutoMode];
286
- // Reset window
287
- self.windowStartTime = currentTime;
288
- self.changeCount = 0;
289
- }
290
- }
291
-
292
- - (void)evaluateAutoMode {
293
- float changesPerSecond = self.changeCount / AUTO_WINDOW_SECONDS;
294
- float threshold = self.internalAutoSensitivity;
295
-
296
- BOOL shouldBeRealtime =
297
- changesPerSecond > (HIGH_CHANGE_THRESHOLD / threshold);
298
- BOOL shouldBeOnChange = changesPerSecond < (LOW_CHANGE_THRESHOLD / threshold);
299
-
300
- if (shouldBeRealtime && !self.isInRealtimeMode) {
301
- [self switchToRealtimeMode];
302
- } else if (shouldBeOnChange && self.isInRealtimeMode) {
303
- [self switchToOnChangeMode];
304
- }
305
- }
306
-
307
- - (void)switchToRealtimeMode {
308
- self.isInRealtimeMode = YES;
309
- [self startRealtimeCapture];
310
- }
311
-
312
- - (void)switchToOnChangeMode {
313
- self.isInRealtimeMode = NO;
314
- [self.captureTimer invalidate];
315
- self.captureTimer = nil;
316
- }
317
-
318
- #pragma mark - Core Capture Logic - Align with Android's performCapture
319
-
320
- - (void)performCapture:(NSString *)trigger {
321
- if (self.isCapturing || self.isDestroyed)
322
- return;
323
-
324
- // Throttle captures to prevent excessive calls
325
- CFTimeInterval currentTime = CACurrentMediaTime();
326
- if (currentTime - self.lastCaptureTime < 1.0 / 60.0) { // Max 60fps
327
- return;
328
- }
329
- self.lastCaptureTime = currentTime;
330
-
331
- self.isCapturing = YES;
332
-
333
- @try {
334
- UIImage *bitmap = [self createBitmap];
335
- if (bitmap) {
336
- [self processBitmap:bitmap trigger:trigger];
337
- }
338
- } @finally {
339
- self.isCapturing = NO;
340
- }
341
- }
342
-
343
- - (UIImage *)createBitmap {
344
- CGSize viewSize = self.bounds.size;
345
-
346
- // Check for valid bounds
347
- if (viewSize.width <= 0 || viewSize.height <= 0) {
348
- return nil;
349
- }
350
-
351
- // Limit maximum image dimensions to prevent memory issues
352
- CGFloat maxDimension = 1920.0; // Max 1920px on either side
353
- CGFloat scale = [UIScreen mainScreen].scale;
354
-
355
- // Calculate actual pixel dimensions
356
- CGFloat pixelWidth = viewSize.width * scale;
357
- CGFloat pixelHeight = viewSize.height * scale;
358
-
359
- // Scale down if too large
360
- if (pixelWidth > maxDimension || pixelHeight > maxDimension) {
361
- CGFloat scaleDown =
362
- MIN(maxDimension / pixelWidth, maxDimension / pixelHeight);
363
- scale = scale * scaleDown;
364
- }
365
-
366
- // Further limit scale on very large views
367
- if (viewSize.width * viewSize.height > 1000000) { // > 1M points
368
- scale = MIN(scale, 1.0);
369
- }
370
-
371
- @autoreleasepool {
372
- UIGraphicsBeginImageContextWithOptions(viewSize, NO, scale);
373
-
374
- CGContextRef context = UIGraphicsGetCurrentContext();
375
- if (!context) {
376
- UIGraphicsEndImageContext();
377
- return nil;
378
- }
379
-
380
- [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO];
381
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
382
- UIGraphicsEndImageContext();
383
-
384
- return image;
385
- }
386
- }
387
-
388
- - (void)processBitmap:(UIImage *)bitmap trigger:(NSString *)trigger {
389
- @autoreleasepool {
390
- if (!bitmap || bitmap.size.width <= 0 || bitmap.size.height <= 0) {
391
- return;
392
- }
393
-
394
- // Check bitmap memory size and skip if too large
395
- CGFloat bitmapMemoryMB =
396
- (bitmap.size.width * bitmap.size.height * 4.0) / (1024.0 * 1024.0);
397
- if (bitmapMemoryMB > 50.0) { // Skip bitmaps larger than 50MB
398
- return;
399
- }
400
-
401
- if (self.bitmapCaptureCallback) {
402
- @try {
403
- [self.bitmapCaptureCallback onBitmapCaptured:bitmap];
404
- } @catch (NSException *exception) {
405
- if (self.bitmapCaptureCallback) {
406
- [self.bitmapCaptureCallback
407
- onCaptureError:[NSString stringWithFormat:@"Callback error: %@",
408
- exception.reason]];
409
- }
410
- }
411
- }
412
-
413
- if (self.onBitmapCapture) {
414
- @autoreleasepool {
415
- NSDictionary *event = @{
416
- @"trigger" : trigger ?: @"unknown",
417
- @"success" : @(YES),
418
- @"x" : @(self.mixX),
419
- @"y" : @(self.mixY),
420
- @"width" : @(self.mixWidth),
421
- @"height" : @(self.mixHeight),
422
- @"zOrder" : @(self.mixZOrder),
423
- @"renderMode" : @(self.mixRenderMode),
424
- @"bitmapWidth" : @(bitmap.size.width),
425
- @"bitmapHeight" : @(bitmap.size.height)
426
- };
427
- self.onBitmapCapture(event);
428
- }
429
- }
430
-
431
- // Clean up old bitmap immediately
432
- if (self.lastBitmap) {
433
- self.lastBitmap = nil;
434
- }
435
-
436
- // For realtime mode, don't keep bitmap reference to reduce memory usage
437
- if ([trigger isEqualToString:@"realtime"]) {
438
- // Bitmap will be auto-released at autoreleasepool end
439
-
440
- // Force memory cleanup every 10 realtime captures
441
- static int realtimeCount = 0;
442
- realtimeCount++;
443
- if (realtimeCount % 10 == 0) {
444
- dispatch_async(
445
- dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
446
- @autoreleasepool {
447
- [[NSURLCache sharedURLCache] removeAllCachedResponses];
448
- }
449
- });
450
- }
451
- } else {
452
- self.lastBitmap = bitmap;
453
- }
454
- }
455
- }
456
-
457
- #pragma mark - Public Methods - Align with Android interface
458
-
459
- // Align with Android's performManualCapture
460
- - (void)performCaptureWithTrigger:(NSString *)trigger {
461
- [self performCapture:trigger];
462
- }
463
-
464
- // Align with Android's setBitmapCaptureCallback
465
- - (void)setBitmapCaptureCallback:(id<VeLiveBitmapCaptureCallback>)callback {
466
- _bitmapCaptureCallback = callback;
467
- }
468
-
469
- #pragma mark - Cleanup - Align with Android
470
-
471
- - (void)cleanup {
472
- self.isDestroyed = YES;
473
- [self stopCapture];
474
-
475
- // Clean up bitmap cache
476
- self.lastBitmap = nil;
477
-
478
- // Clean up callback references, avoid circular references
479
- self.bitmapCaptureCallback = nil;
480
- }
481
-
482
- - (void)dealloc {
483
- // Remove from global cache
484
- if (self.viewId) {
485
- NSMutableDictionary *cachedViews = [VeLiveMixerHelper cachedMixedViews];
486
- if (cachedViews) {
487
- [cachedViews removeObjectForKey:self.viewId];
488
- }
489
- }
490
- }
491
-
492
- #pragma mark - View Conversion Methods
493
-
494
- - (UIImage *)snapshotIncludeSubviews {
495
- CGSize viewSize = self.bounds.size;
496
-
497
- // Check for valid bounds
498
- if (viewSize.width <= 0 || viewSize.height <= 0) {
499
- return nil;
500
- }
501
-
502
- // Limit maximum image dimensions to prevent memory issues
503
- CGFloat maxDimension = 1920.0; // Max 1920px on either side
504
- CGFloat scale = [UIScreen mainScreen].scale;
505
-
506
- // Calculate actual pixel dimensions
507
- CGFloat pixelWidth = viewSize.width * scale;
508
- CGFloat pixelHeight = viewSize.height * scale;
509
-
510
- // Scale down if too large
511
- if (pixelWidth > maxDimension || pixelHeight > maxDimension) {
512
- CGFloat scaleDown =
513
- MIN(maxDimension / pixelWidth, maxDimension / pixelHeight);
514
- scale = scale * scaleDown;
515
- }
516
-
517
- // Further limit scale on very large views
518
- if (viewSize.width * viewSize.height > 1000000) { // > 1M points
519
- scale = MIN(scale, 1.0);
520
- }
521
-
522
- @autoreleasepool {
523
- UIGraphicsBeginImageContextWithOptions(viewSize, NO, scale);
524
-
525
- CGContextRef context = UIGraphicsGetCurrentContext();
526
- if (!context) {
527
- UIGraphicsEndImageContext();
528
- return nil;
529
- }
530
-
531
- [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO];
532
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
533
- UIGraphicsEndImageContext();
534
-
535
- return image;
536
- }
537
- }
538
-
539
- - (CVPixelBufferRef)createPixelBuffer {
540
- // Implement pixel buffer creation (corresponds to Android's ByteBuffer)
541
- return NULL; // Temporary return NULL, implementation based on needs
542
- }
543
-
544
- - (CMSampleBufferRef)createSampleBuffer {
545
- // Implement sample buffer creation (corresponds to Android's VideoFrame)
546
- return NULL; // Temporary return NULL, implementation based on needs
547
- }
548
-
549
- #pragma mark - React Native Child View Support - Focus on RN subview management
550
-
551
- // React Native subview insertion - This is the main method called by RN
552
- // framework
553
- - (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex {
554
- // Process directly on main thread because React Native ensures thread safety
555
- [super insertSubview:subview atIndex:atIndex];
556
- [self setSubViewAutoLayout:subview];
557
- }
558
-
559
- - (void)removeReactSubview:(UIView *)subview {
560
- [subview removeFromSuperview];
561
- }
562
-
563
- - (NSArray<UIView *> *)reactSubviews {
564
- return [self subviews];
565
- }
566
-
567
- // Set Auto Layout constraints - Ensure subview fills parent view
568
- - (void)setSubViewAutoLayout:(UIView *)subview {
569
- // Disable automatic conversion, use constraints layout
570
- subview.translatesAutoresizingMaskIntoConstraints = NO;
571
-
572
- // Set four-side constraints, let subview fill parent view
573
- [NSLayoutConstraint activateConstraints:@[
574
- [subview.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
575
- [subview.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
576
- [subview.topAnchor constraintEqualToAnchor:self.topAnchor],
577
- [subview.bottomAnchor constraintEqualToAnchor:self.bottomAnchor]
578
- ]];
579
- }
580
-
581
- // Override layoutSubviews to ensure correct subview layout
582
- - (void)layoutSubviews {
583
- [super layoutSubviews];
584
- if (self.isDestroyed)
585
- return;
586
-
587
- // Original capture logic
588
- if ([self.internalCaptureMode isEqualToString:@"onchange"]) {
589
- [self performCapture:@"onchange"];
590
- } else if ([self.internalCaptureMode isEqualToString:@"auto"]) {
591
- [self handleAutoModeChange];
592
- }
593
- }
594
-
595
- // Ensure UIView can correctly display background color and subviews
596
- - (void)setBackgroundColor:(UIColor *)backgroundColor {
597
- [super setBackgroundColor:backgroundColor];
598
- }
599
-
600
- @end
@@ -1,92 +0,0 @@
1
- //
2
- // VeLiveMixerViewManager.m
3
- // react-native-live-push
4
- //
5
- // Created to manage VeLiveMixerView React Native component
6
- //
7
-
8
- #import "VeLiveMixerView.h"
9
- #import <Foundation/Foundation.h>
10
- #import <React/RCTComponent.h>
11
- #import <React/RCTViewManager.h>
12
- #import <UIKit/UIKit.h>
13
-
14
- @interface VeLiveMixerViewManager : RCTViewManager
15
- @end
16
-
17
- @implementation VeLiveMixerViewManager
18
-
19
- + (BOOL)requiresMainQueueSetup {
20
- return YES;
21
- }
22
-
23
- RCT_EXPORT_MODULE(VeLiveMixView)
24
-
25
- - (VeLiveMixerUIView *)view {
26
- VeLiveMixerUIView *view = [[VeLiveMixerUIView alloc] init];
27
- view.accessibilityLabel = @"VeLiveMixerUIView";
28
- return view;
29
- }
30
-
31
- // 导出视图ID属性 - 使用自定义属性处理
32
- RCT_CUSTOM_VIEW_PROPERTY(viewId, NSString, VeLiveMixerUIView) {
33
- if (json == nil) {
34
- return;
35
- }
36
-
37
- NSString *viewId = [RCTConvert NSString:json];
38
- [view setViewId:viewId];
39
- }
40
-
41
- // 导出混合配置属性 - 与Android保持一致的属性名
42
- RCT_CUSTOM_VIEW_PROPERTY(x, NSNumber, VeLiveMixerUIView) {
43
- NSNumber *x = [RCTConvert NSNumber:json];
44
- [view setX:x];
45
- }
46
-
47
- RCT_CUSTOM_VIEW_PROPERTY(y, NSNumber, VeLiveMixerUIView) {
48
- NSNumber *y = [RCTConvert NSNumber:json];
49
- [view setY:y];
50
- }
51
-
52
- RCT_CUSTOM_VIEW_PROPERTY(width, NSNumber, VeLiveMixerUIView) {
53
- NSNumber *width = [RCTConvert NSNumber:json];
54
- [view setWidth:width];
55
- }
56
-
57
- RCT_CUSTOM_VIEW_PROPERTY(height, NSNumber, VeLiveMixerUIView) {
58
- NSNumber *height = [RCTConvert NSNumber:json];
59
- [view setHeight:height];
60
- }
61
-
62
- RCT_CUSTOM_VIEW_PROPERTY(zOrder, NSNumber, VeLiveMixerUIView) {
63
- NSNumber *zOrder = [RCTConvert NSNumber:json];
64
- [view setZOrder:zOrder];
65
- }
66
-
67
- RCT_CUSTOM_VIEW_PROPERTY(renderMode, NSNumber, VeLiveMixerUIView) {
68
- NSNumber *renderMode = [RCTConvert NSNumber:json];
69
- [view setRenderMode:renderMode];
70
- }
71
-
72
- // 导出捕获配置属性
73
- RCT_CUSTOM_VIEW_PROPERTY(captureMode, NSString, VeLiveMixerUIView) {
74
- NSString *captureMode = [RCTConvert NSString:json];
75
- if (captureMode != nil) {
76
- [view setCaptureMode:captureMode];
77
- } else {
78
- [view setCaptureMode:@"onchange"];
79
- }
80
- }
81
-
82
- RCT_CUSTOM_VIEW_PROPERTY(captureFramerate, NSNumber, VeLiveMixerUIView) {
83
- NSNumber *framerate = [RCTConvert NSNumber:json];
84
- [view setCaptureFramerate:framerate];
85
- }
86
-
87
- RCT_CUSTOM_VIEW_PROPERTY(autoSensitivity, NSNumber, VeLiveMixerUIView) {
88
- NSNumber *sensitivity = [RCTConvert NSNumber:json];
89
- [view setAutoSensitivity:sensitivity];
90
- }
91
-
92
- @end