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

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.
@@ -254,6 +254,11 @@ public class MixerManager {
254
254
  }
255
255
  } catch (Exception e) {
256
256
  // Ignore
257
+ } finally {
258
+ if (bitmap != null && !bitmap.isRecycled()) {
259
+ bitmap.recycle();
260
+ }
261
+ textureMgr.cleanup();
257
262
  }
258
263
  }
259
264
  });
@@ -255,7 +255,8 @@ public class MixerView extends FrameLayout {
255
255
  }
256
256
 
257
257
  long currentTime = System.currentTimeMillis();
258
- if (currentTime - lastCaptureTime < 16) {
258
+ long minInterval = 33; // 30 FPS ~ 33ms per frame
259
+ if (currentTime - lastCaptureTime < minInterval) {
259
260
  return;
260
261
  }
261
262
  lastCaptureTime = currentTime;
@@ -316,6 +317,7 @@ public class MixerView extends FrameLayout {
316
317
  // Call callback first if set (for MixerManager)
317
318
  if (bitmapCaptureCallback != null) {
318
319
  try {
320
+ // only capture if the callback is set
319
321
  bitmapCaptureCallback.onBitmapCaptured(bitmap);
320
322
  } catch (Exception e) {
321
323
  if (bitmapCaptureCallback != null) {
@@ -339,6 +341,12 @@ public class MixerView extends FrameLayout {
339
341
  } catch (IllegalStateException e) {
340
342
  // Ignore
341
343
  }
344
+
345
+ // if no callback, recycle immediately to avoid accumulation
346
+ if (bitmap != null && !bitmap.isRecycled()) {
347
+ bitmap.recycle();
348
+ return;
349
+ }
342
350
  }
343
351
 
344
352
  // Clean up old bitmap
@@ -137,14 +137,14 @@ public class TextureMgr {
137
137
  GLThreadManager.getMainGlHandle().post(() -> {
138
138
  if (texture > 0) {
139
139
  Bitmap processedBitmap = null;
140
+ boolean needRecycle = false;
140
141
  try {
141
142
  if (bitmap == null || bitmap.isRecycled()) {
142
143
  return;
143
144
  }
144
-
145
145
  GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
146
146
  processedBitmap = YuvHelper.rotateBitmap(bitmap, 0, false, true);
147
-
147
+ needRecycle = (processedBitmap != null && processedBitmap != bitmap);
148
148
  if (processedBitmap != null && !processedBitmap.isRecycled()) {
149
149
  GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, processedBitmap, 0);
150
150
  GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
@@ -158,7 +158,7 @@ public class TextureMgr {
158
158
  } catch (Exception e) {
159
159
  // Ignore
160
160
  } finally {
161
- if (processedBitmap != null && processedBitmap != bitmap && !processedBitmap.isRecycled()) {
161
+ if (needRecycle && processedBitmap != null && !processedBitmap.isRecycled()) {
162
162
  processedBitmap.recycle();
163
163
  }
164
164
  }
@@ -12,13 +12,26 @@ import android.renderscript.Type;
12
12
  import java.nio.ByteBuffer;
13
13
 
14
14
  public class YuvHelper {
15
+ private static RenderScript globalRS = null;
16
+ public static synchronized RenderScript getGlobalRS(Context context) {
17
+ if (globalRS == null) {
18
+ globalRS = RenderScript.create(context.getApplicationContext());
19
+ }
20
+ return globalRS;
21
+ }
22
+ public static void destroyGlobalRS() {
23
+ if (globalRS != null) {
24
+ globalRS.destroy();
25
+ globalRS = null;
26
+ }
27
+ }
15
28
  public static class NV21ToBitmap {
16
29
  private RenderScript rs;
17
30
  private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic;
18
31
  private Type.Builder yuvType, rgbaType;
19
32
 
20
33
  public NV21ToBitmap(Context context) {
21
- rs = RenderScript.create(context);
34
+ rs = YuvHelper.getGlobalRS(context);
22
35
  yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
23
36
  yuvType = new Type.Builder(rs, Element.U8(rs));
24
37
  rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs));
@@ -30,10 +43,8 @@ public class YuvHelper {
30
43
  yuvToRgbIntrinsic.destroy();
31
44
  yuvToRgbIntrinsic = null;
32
45
  }
33
- if (rs != null) {
34
- rs.destroy();
35
- rs = null;
36
- }
46
+ // 不销毁全局 rs
47
+ // rs = null;
37
48
  } catch (Exception e) {
38
49
  // Ignore
39
50
  }
@@ -6,11 +6,11 @@
6
6
  //
7
7
 
8
8
  #import "VeLiveMixerHelper.h"
9
- #include <objc/NSObjCRuntime.h>
10
- #import <UIKit/UIKit.h>
11
9
  #import <TTSDKLivePushRTS/TTSDKLivePushRTS.h>
10
+ #import <UIKit/UIKit.h>
12
11
  #import <mach/mach.h>
13
12
  #import <mach/task_info.h>
13
+ #include <objc/NSObjCRuntime.h>
14
14
 
15
15
  static NSString *TAG = @"VeLiveMixerHelper";
16
16
 
@@ -22,36 +22,42 @@ static NSString *TAG = @"VeLiveMixerHelper";
22
22
 
23
23
  @interface VeLiveMixerHelper ()
24
24
 
25
- @property(nonatomic, strong) NSMutableDictionary<NSString *, NSDictionary *> *mixedViewLayout;
26
- @property(nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *viewIdToStreamId;
27
- @property(nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *pendingCallbacks;
28
- @property(nonatomic, strong) NSMutableDictionary<NSString *, VeLiveMixerBitmapCallback *> *callbacks;
29
- @property (nonatomic, strong) NSTimer *memoryMonitorTimer;
25
+ @property(nonatomic, strong)
26
+ NSMutableDictionary<NSString *, NSDictionary *> *mixedViewLayout;
27
+ @property(nonatomic, strong)
28
+ NSMutableDictionary<NSString *, NSNumber *> *viewIdToStreamId;
29
+ @property(nonatomic, strong)
30
+ NSMutableDictionary<NSString *, NSNumber *> *pendingCallbacks;
31
+ @property(nonatomic, strong)
32
+ NSMutableDictionary<NSString *, VeLiveMixerBitmapCallback *> *callbacks;
33
+ @property(nonatomic, strong) NSTimer *memoryMonitorTimer;
30
34
 
31
35
  @end
32
36
 
33
37
  #pragma mark - VeLiveMixerBitmapCallback Declaration
34
38
 
35
39
  @interface VeLiveMixerBitmapCallback : NSObject <VeLiveBitmapCaptureCallback>
36
- @property (nonatomic, assign) int streamId;
40
+ @property(nonatomic, assign) int streamId;
37
41
  - (instancetype)initWithStreamId:(int)streamId;
38
42
  @end
39
43
 
40
44
  @implementation VeLiveMixerHelper
41
45
 
42
46
  // 对齐Android的static cachedMixedViews
43
- static NSMutableDictionary<NSString *, VeLiveMixerUIView *> *_cachedMixedViews = nil;
47
+ static NSMutableDictionary<NSString *, VeLiveMixerUIView *> *_cachedMixedViews =
48
+ nil;
44
49
  static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释放
45
50
 
46
51
  + (NSMutableDictionary<NSString *, VeLiveMixerUIView *> *)cachedMixedViews {
47
- if (!_cachedMixedViews) {
48
- _cachedMixedViews = [[NSMutableDictionary alloc] init];
49
- }
50
- return _cachedMixedViews;
52
+ if (!_cachedMixedViews) {
53
+ _cachedMixedViews = [[NSMutableDictionary alloc] init];
54
+ }
55
+ return _cachedMixedViews;
51
56
  }
52
57
 
53
- + (void)setCachedMixedViews:(NSMutableDictionary<NSString *, VeLiveMixerUIView *> *)cachedMixedViews {
54
- _cachedMixedViews = cachedMixedViews;
58
+ + (void)setCachedMixedViews:
59
+ (NSMutableDictionary<NSString *, VeLiveMixerUIView *> *)cachedMixedViews {
60
+ _cachedMixedViews = cachedMixedViews;
55
61
  }
56
62
 
57
63
  - (instancetype)init {
@@ -77,7 +83,7 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
77
83
  _viewIdToStreamId = [[NSMutableDictionary alloc] init];
78
84
  _pendingCallbacks = [[NSMutableDictionary alloc] init];
79
85
  _callbacks = [[NSMutableDictionary alloc] init];
80
-
86
+
81
87
  currentInstance = self;
82
88
  }
83
89
 
@@ -115,7 +121,7 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
115
121
 
116
122
  - (void)setPusher:(VeLivePusher *)pusher {
117
123
  _pusher = pusher;
118
-
124
+
119
125
  if (currentInstance != self) {
120
126
  currentInstance = self;
121
127
  }
@@ -126,30 +132,31 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
126
132
  if (!self.pusher) {
127
133
  return -1;
128
134
  }
129
-
135
+
130
136
  VeLiveMixerUIView *view = [VeLiveMixerHelper cachedMixedViews][viewId];
131
137
  if (![view isKindOfClass:[VeLiveMixerUIView class]]) {
132
138
  // View not ready, store pending callback
133
139
  }
134
-
140
+
135
141
  NSNumber *existingStreamId = [self.viewIdToStreamId objectForKey:viewId];
136
- if(existingStreamId != nil) {
142
+ if (existingStreamId != nil) {
137
143
  return [existingStreamId intValue];
138
144
  }
139
-
145
+
140
146
  int videoStreamId = [[self.pusher getMixerManager] addVideoStream];
141
-
147
+
142
148
  NSDictionary *layout = @{
143
- @"x": viewInfo[@"x"] ?: @(0),
144
- @"y": viewInfo[@"y"] ?: @(0),
145
- @"width": viewInfo[@"width"] ?: @(0),
146
- @"height": viewInfo[@"height"] ?: @(0),
147
- @"zOrder": viewInfo[@"zOrder"] ?: @(1),
148
- @"renderMode": viewInfo[@"renderMode"] ?: @(0),
149
- @"streamId": @(videoStreamId)
149
+ @"x" : viewInfo[@"x"] ?: @(0),
150
+ @"y" : viewInfo[@"y"] ?: @(0),
151
+ @"width" : viewInfo[@"width"] ?: @(0),
152
+ @"height" : viewInfo[@"height"] ?: @(0),
153
+ @"zOrder" : viewInfo[@"zOrder"] ?: @(1),
154
+ @"renderMode" : viewInfo[@"renderMode"] ?: @(0),
155
+ @"streamId" : @(videoStreamId)
150
156
  };
151
-
152
- VeLiveStreamMixDescription *description = [[VeLiveStreamMixDescription alloc] init];
157
+
158
+ VeLiveStreamMixDescription *description =
159
+ [[VeLiveStreamMixDescription alloc] init];
153
160
  VeLiveMixVideoLayout *videoLayout = [[VeLiveMixVideoLayout alloc] init];
154
161
  videoLayout.streamId = videoStreamId;
155
162
  videoLayout.x = [viewInfo[@"x"] floatValue];
@@ -158,18 +165,18 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
158
165
  videoLayout.height = [viewInfo[@"height"] floatValue];
159
166
  videoLayout.zOrder = [viewInfo[@"zOrder"] intValue];
160
167
  videoLayout.renderMode = [viewInfo[@"renderMode"] intValue];
161
- description.mixVideoStreams = @[videoLayout];
168
+ description.mixVideoStreams = @[ videoLayout ];
162
169
  [self.pusher.getMixerManager updateStreamMixDescription:description];
163
-
170
+
164
171
  [self.mixedViewLayout setObject:layout forKey:viewId];
165
172
  [self.viewIdToStreamId setObject:@(videoStreamId) forKey:viewId];
166
-
173
+
167
174
  if ([view isKindOfClass:[VeLiveMixerUIView class]]) {
168
175
  [VeLiveMixerHelper setupCallbackForMixerView:view streamId:videoStreamId];
169
176
  } else {
170
177
  [self.pendingCallbacks setObject:@(videoStreamId) forKey:viewId];
171
178
  }
172
-
179
+
173
180
  return videoStreamId;
174
181
  } @catch (NSException *exception) {
175
182
  return -1;
@@ -182,19 +189,24 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
182
189
  if (!layout) {
183
190
  return NO;
184
191
  }
185
-
192
+
186
193
  NSNumber *streamIdNumber = [self.viewIdToStreamId objectForKey:viewId];
187
194
  int videoStreamId = [streamIdNumber intValue];
188
-
195
+
189
196
  NSMutableDictionary *updatedLayout = [layout mutableCopy];
190
197
  [updatedLayout setObject:(viewInfo[@"x"] ?: layout[@"x"]) forKey:@"x"];
191
198
  [updatedLayout setObject:(viewInfo[@"y"] ?: layout[@"y"]) forKey:@"y"];
192
- [updatedLayout setObject:(viewInfo[@"width"] ?: layout[@"width"]) forKey:@"width"];
193
- [updatedLayout setObject:(viewInfo[@"height"] ?: layout[@"height"]) forKey:@"height"];
194
- [updatedLayout setObject:(viewInfo[@"zOrder"] ?: layout[@"zOrder"]) forKey:@"zOrder"];
195
- [updatedLayout setObject:(viewInfo[@"renderMode"] ?: layout[@"renderMode"]) forKey:@"renderMode"];
196
-
197
- VeLiveStreamMixDescription *description = [[VeLiveStreamMixDescription alloc] init];
199
+ [updatedLayout setObject:(viewInfo[@"width"] ?: layout[@"width"])
200
+ forKey:@"width"];
201
+ [updatedLayout setObject:(viewInfo[@"height"] ?: layout[@"height"])
202
+ forKey:@"height"];
203
+ [updatedLayout setObject:(viewInfo[@"zOrder"] ?: layout[@"zOrder"])
204
+ forKey:@"zOrder"];
205
+ [updatedLayout setObject:(viewInfo[@"renderMode"] ?: layout[@"renderMode"])
206
+ forKey:@"renderMode"];
207
+
208
+ VeLiveStreamMixDescription *description =
209
+ [[VeLiveStreamMixDescription alloc] init];
198
210
  VeLiveMixVideoLayout *videoLayout = [[VeLiveMixVideoLayout alloc] init];
199
211
  videoLayout.streamId = videoStreamId;
200
212
  videoLayout.x = [updatedLayout[@"x"] floatValue];
@@ -203,14 +215,15 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
203
215
  videoLayout.height = [updatedLayout[@"height"] floatValue];
204
216
  videoLayout.zOrder = [updatedLayout[@"zOrder"] intValue];
205
217
  videoLayout.renderMode = [updatedLayout[@"renderMode"] intValue];
206
- description.mixVideoStreams = @[videoLayout];
218
+ description.mixVideoStreams = @[ videoLayout ];
207
219
  [self.pusher.getMixerManager updateStreamMixDescription:description];
208
-
220
+
209
221
  [self.mixedViewLayout setObject:updatedLayout forKey:viewId];
210
-
211
- VeLiveMixerUIView *mixerView = [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
222
+
223
+ VeLiveMixerUIView *mixerView =
224
+ [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
212
225
  [mixerView performCaptureWithTrigger:@"update"];
213
-
226
+
214
227
  return YES;
215
228
  } @catch (NSException *exception) {
216
229
  return NO;
@@ -223,26 +236,27 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
223
236
  if (!layout) {
224
237
  return NO;
225
238
  }
226
-
239
+
227
240
  NSNumber *streamIdNumber = [self.viewIdToStreamId objectForKey:viewId];
228
241
  if (streamIdNumber) {
229
242
  int streamId = [streamIdNumber intValue];
230
243
  [self.pusher.getMixerManager removeVideoStream:streamId];
231
-
244
+
232
245
  NSString *callbackKey = [NSString stringWithFormat:@"%d", streamId];
233
246
  [self.callbacks removeObjectForKey:callbackKey];
234
247
  }
235
-
248
+
236
249
  [self.viewIdToStreamId removeObjectForKey:viewId];
237
250
  [self.pendingCallbacks removeObjectForKey:viewId];
238
-
239
- VeLiveMixerUIView *view = [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
251
+
252
+ VeLiveMixerUIView *view =
253
+ [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
240
254
  if ([view isKindOfClass:[VeLiveMixerUIView class]]) {
241
255
  view.bitmapCaptureCallback = nil;
242
256
  }
243
-
257
+
244
258
  [self.mixedViewLayout removeObjectForKey:viewId];
245
-
259
+
246
260
  return YES;
247
261
  } @catch (NSException *exception) {
248
262
  return NO;
@@ -250,7 +264,8 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
250
264
  }
251
265
 
252
266
  - (void)captureView:(NSString *)viewId {
253
- VeLiveMixerUIView *view = [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
267
+ VeLiveMixerUIView *view =
268
+ [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
254
269
  if ([view isKindOfClass:[VeLiveMixerUIView class]]) {
255
270
  [view performCaptureWithTrigger:@"manual"];
256
271
  }
@@ -258,55 +273,64 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
258
273
 
259
274
  #pragma mark - Static Methods
260
275
 
261
- + (void)setupCallbackForMixerView:(VeLiveMixerUIView *)mixerView streamId:(int)streamId {
276
+ + (void)setupCallbackForMixerView:(VeLiveMixerUIView *)mixerView
277
+ streamId:(int)streamId {
262
278
  if (mixerView == nil) {
263
279
  return;
264
280
  }
265
-
281
+
266
282
  VeLiveMixerHelper *instance = [VeLiveMixerHelper findActiveMixerManager];
267
283
  if (!instance) {
268
284
  return;
269
285
  }
270
-
271
- VeLiveMixerBitmapCallback *callback = [[VeLiveMixerBitmapCallback alloc] initWithStreamId:streamId];
272
-
286
+
287
+ VeLiveMixerBitmapCallback *callback =
288
+ [[VeLiveMixerBitmapCallback alloc] initWithStreamId:streamId];
289
+
273
290
  NSString *callbackKey = [NSString stringWithFormat:@"%d", streamId];
274
291
  [instance.callbacks setObject:callback forKey:callbackKey];
275
-
292
+
276
293
  mixerView.bitmapCaptureCallback = callback;
277
-
278
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
279
- @try {
280
- if (mixerView && mixerView.bitmapCaptureCallback) {
281
- VeLiveMixerHelper *instance = [VeLiveMixerHelper findActiveMixerManager];
282
- if (instance && instance.pusher) {
283
- @try {
284
- NSString *viewId = mixerView.viewId;
285
- NSDictionary *layout = [instance.mixedViewLayout objectForKey:viewId];
286
- if (layout) {
287
- VeLiveStreamMixDescription *description = [[VeLiveStreamMixDescription alloc] init];
288
- VeLiveMixVideoLayout *videoLayout = [[VeLiveMixVideoLayout alloc] init];
289
- videoLayout.streamId = streamId;
290
- videoLayout.x = [layout[@"x"] floatValue];
291
- videoLayout.y = [layout[@"y"] floatValue];
292
- videoLayout.width = [layout[@"width"] floatValue];
293
- videoLayout.height = [layout[@"height"] floatValue];
294
- videoLayout.zOrder = [layout[@"zOrder"] intValue];
295
- videoLayout.renderMode = [layout[@"renderMode"] intValue];
296
- description.mixVideoStreams = @[videoLayout];
297
- [instance.pusher.getMixerManager updateStreamMixDescription:description];
294
+
295
+ dispatch_after(
296
+ dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)),
297
+ dispatch_get_main_queue(), ^{
298
+ @try {
299
+ if (mixerView && mixerView.bitmapCaptureCallback) {
300
+ VeLiveMixerHelper *instance =
301
+ [VeLiveMixerHelper findActiveMixerManager];
302
+ if (instance && instance.pusher) {
303
+ @try {
304
+ NSString *viewId = mixerView.viewId;
305
+ NSDictionary *layout =
306
+ [instance.mixedViewLayout objectForKey:viewId];
307
+ if (layout) {
308
+ VeLiveStreamMixDescription *description =
309
+ [[VeLiveStreamMixDescription alloc] init];
310
+ VeLiveMixVideoLayout *videoLayout =
311
+ [[VeLiveMixVideoLayout alloc] init];
312
+ videoLayout.streamId = streamId;
313
+ videoLayout.x = [layout[@"x"] floatValue];
314
+ videoLayout.y = [layout[@"y"] floatValue];
315
+ videoLayout.width = [layout[@"width"] floatValue];
316
+ videoLayout.height = [layout[@"height"] floatValue];
317
+ videoLayout.zOrder = [layout[@"zOrder"] intValue];
318
+ videoLayout.renderMode = [layout[@"renderMode"] intValue];
319
+ description.mixVideoStreams = @[ videoLayout ];
320
+ [instance.pusher.getMixerManager
321
+ updateStreamMixDescription:description];
322
+ }
323
+ } @catch (NSException *e) {
324
+ // Ignore
325
+ }
298
326
  }
299
- } @catch (NSException *e) {
300
- // Ignore
327
+
328
+ [mixerView performCaptureWithTrigger:@"update"];
301
329
  }
330
+ } @catch (NSException *exception) {
331
+ // Ignore
302
332
  }
303
-
304
- [mixerView performCaptureWithTrigger:@"update"];
305
- }
306
- } @catch (NSException *exception) {
307
- // Ignore
308
- }
309
- });
333
+ });
310
334
  }
311
335
 
312
336
  + (void)sendBitmapToMixerStatic:(int)streamId bitmap:(UIImage *)bitmap {
@@ -320,15 +344,18 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
320
344
  return currentInstance;
321
345
  }
322
346
 
323
- + (void)onViewReady:(NSString *)viewId mixerView:(VeLiveMixerUIView *)mixerView {
347
+ + (void)onViewReady:(NSString *)viewId
348
+ mixerView:(VeLiveMixerUIView *)mixerView {
324
349
  @try {
325
350
  VeLiveMixerHelper *instance = [VeLiveMixerHelper findActiveMixerManager];
326
351
  if (instance != nil) {
327
- NSNumber *streamIdNumber = [instance.pendingCallbacks objectForKey:viewId];
352
+ NSNumber *streamIdNumber =
353
+ [instance.pendingCallbacks objectForKey:viewId];
328
354
  if (streamIdNumber != nil) {
329
355
  int streamId = [streamIdNumber intValue];
330
356
  [instance.pendingCallbacks removeObjectForKey:viewId];
331
- [VeLiveMixerHelper setupCallbackForMixerView:mixerView streamId:streamId];
357
+ [VeLiveMixerHelper setupCallbackForMixerView:mixerView
358
+ streamId:streamId];
332
359
  }
333
360
  }
334
361
  } @catch (NSException *exception) {
@@ -338,36 +365,42 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
338
365
 
339
366
  - (void)cleanup {
340
367
  [self stopMemoryMonitoring];
341
-
368
+
342
369
  for (NSString *viewId in self.mixedViewLayout.allKeys) {
343
- VeLiveMixerUIView *view = [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
370
+ VeLiveMixerUIView *view =
371
+ [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
344
372
  if ([view isKindOfClass:[VeLiveMixerUIView class]]) {
345
373
  view.bitmapCaptureCallback = nil;
346
374
  }
347
375
  }
348
-
376
+
349
377
  [self.mixedViewLayout removeAllObjects];
350
378
  [self.pendingCallbacks removeAllObjects];
351
379
  [self.callbacks removeAllObjects];
352
-
380
+
353
381
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
354
382
  @autoreleasepool {
355
383
  [[NSURLCache sharedURLCache] removeAllCachedResponses];
356
384
  [[NSURLCache sharedURLCache] setMemoryCapacity:0];
357
385
  [[NSURLCache sharedURLCache] setMemoryCapacity:10 * 1024 * 1024];
358
-
359
- [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification object:nil];
360
-
361
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
362
- // Final cleanup completed
363
- });
386
+
387
+ [[NSNotificationCenter defaultCenter]
388
+ postNotificationName:UIApplicationDidReceiveMemoryWarningNotification
389
+ object:nil];
390
+
391
+ dispatch_after(
392
+ dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)),
393
+ dispatch_get_main_queue(),
394
+ ^{
395
+ // Final cleanup completed
396
+ });
364
397
  }
365
398
  });
366
399
  }
367
400
 
368
401
  - (void)dealloc {
369
402
  [self cleanup];
370
-
403
+
371
404
  if (currentInstance == self) {
372
405
  currentInstance = nil;
373
406
  }
@@ -376,11 +409,12 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
376
409
  #pragma mark - Memory Monitoring
377
410
 
378
411
  - (void)startMemoryMonitoring {
379
- self.memoryMonitorTimer = [NSTimer scheduledTimerWithTimeInterval:30.0
380
- target:self
381
- selector:@selector(checkMemoryUsage)
382
- userInfo:nil
383
- repeats:YES];
412
+ self.memoryMonitorTimer =
413
+ [NSTimer scheduledTimerWithTimeInterval:30.0
414
+ target:self
415
+ selector:@selector(checkMemoryUsage)
416
+ userInfo:nil
417
+ repeats:YES];
384
418
  }
385
419
 
386
420
  - (void)stopMemoryMonitoring {
@@ -394,11 +428,12 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
394
428
  @autoreleasepool {
395
429
  struct task_basic_info info;
396
430
  mach_msg_type_number_t size = TASK_BASIC_INFO_COUNT;
397
- kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
398
-
431
+ kern_return_t kerr =
432
+ task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
433
+
399
434
  if (kerr == KERN_SUCCESS) {
400
435
  double memoryUsageMB = info.resident_size / 1024.0 / 1024.0;
401
-
436
+
402
437
  if (memoryUsageMB > 200.0) {
403
438
  [self performMemoryCleanup];
404
439
  }
@@ -415,20 +450,24 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
415
450
  if ([view isKindOfClass:[VeLiveMixerUIView class]]) {
416
451
  if ([view.captureMode isEqualToString:@"realtime"]) {
417
452
  [view stopCapture];
418
-
419
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
420
- if (view && [cachedViews objectForKey:viewId] == view) {
421
- [view startCapture];
422
- }
423
- });
453
+
454
+ dispatch_after(
455
+ dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)),
456
+ dispatch_get_main_queue(), ^{
457
+ if (view && [cachedViews objectForKey:viewId] == view) {
458
+ [view startCapture];
459
+ }
460
+ });
424
461
  }
425
462
  }
426
463
  }
427
-
464
+
428
465
  [[NSURLCache sharedURLCache] removeAllCachedResponses];
429
466
  [[NSURLCache sharedURLCache] setMemoryCapacity:5 * 1024 * 1024];
430
-
431
- [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification object:nil];
467
+
468
+ [[NSNotificationCenter defaultCenter]
469
+ postNotificationName:UIApplicationDidReceiveMemoryWarningNotification
470
+ object:nil];
432
471
  }
433
472
  });
434
473
  }
@@ -440,34 +479,26 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
440
479
  if (!self.pusher || !bitmap) {
441
480
  return;
442
481
  }
443
-
482
+
444
483
  CVPixelBufferRef pixelBuffer = NULL;
445
-
484
+
446
485
  @try {
447
486
  pixelBuffer = [self pixelBufferFromUIImage:bitmap];
448
487
  if (!pixelBuffer) {
449
488
  return;
450
489
  }
451
-
490
+
452
491
  VeLiveVideoFrame *videoFrame = [[VeLiveVideoFrame alloc] init];
453
492
  videoFrame.bufferType = VeLiveVideoBufferTypePixelBuffer;
454
493
  videoFrame.pts = CMTimeMakeWithSeconds(CACurrentMediaTime(), 1000000000);
455
494
  videoFrame.pixelBuffer = pixelBuffer;
456
-
457
- __block CVPixelBufferRef bufferToRelease = pixelBuffer;
458
- [videoFrame setReleaseCallback:^{
459
- @autoreleasepool {
460
- if (bufferToRelease) {
461
- CVPixelBufferRelease(bufferToRelease);
462
- bufferToRelease = NULL;
463
- }
464
- }
465
- }];
466
-
467
- [[self.pusher getMixerManager] sendCustomVideoFrame:videoFrame streamId:streamId];
468
-
495
+
496
+ [[self.pusher getMixerManager] sendCustomVideoFrame:videoFrame
497
+ streamId:streamId];
498
+ CVPixelBufferRelease(pixelBuffer);
499
+
469
500
  pixelBuffer = NULL;
470
-
501
+
471
502
  } @catch (NSException *exception) {
472
503
  if (pixelBuffer) {
473
504
  CVPixelBufferRelease(pixelBuffer);
@@ -483,55 +514,53 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
483
514
  if (!image) {
484
515
  return NULL;
485
516
  }
486
-
517
+
487
518
  CGImageRef cgImage = image.CGImage;
488
519
  if (!cgImage) {
489
520
  return NULL;
490
521
  }
491
-
522
+
492
523
  CGFloat width = CGImageGetWidth(cgImage);
493
524
  CGFloat height = CGImageGetHeight(cgImage);
494
-
525
+
495
526
  NSDictionary *options = @{
496
- (NSString *)kCVPixelBufferCGImageCompatibilityKey: @YES,
497
- (NSString *)kCVPixelBufferCGBitmapContextCompatibilityKey: @YES,
498
- (NSString *)kCVPixelBufferIOSurfacePropertiesKey: @{}
527
+ (NSString *)kCVPixelBufferCGImageCompatibilityKey : @YES,
528
+ (NSString *)kCVPixelBufferCGBitmapContextCompatibilityKey : @YES,
529
+ (NSString *)kCVPixelBufferIOSurfacePropertiesKey : @{}
499
530
  };
500
-
531
+
501
532
  CVPixelBufferRef pixelBuffer = NULL;
502
- CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
503
- width, height,
504
- kCVPixelFormatType_32BGRA,
505
- (__bridge CFDictionaryRef)options,
506
- &pixelBuffer);
507
-
533
+ CVReturn status = CVPixelBufferCreate(
534
+ kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA,
535
+ (__bridge CFDictionaryRef)options, &pixelBuffer);
536
+
508
537
  if (status != kCVReturnSuccess || !pixelBuffer) {
509
538
  return NULL;
510
539
  }
511
-
540
+
512
541
  CVPixelBufferLockBaseAddress(pixelBuffer, 0);
513
-
542
+
514
543
  void *pixelData = CVPixelBufferGetBaseAddress(pixelBuffer);
515
544
  size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);
516
-
545
+
517
546
  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
518
- CGContextRef context = CGBitmapContextCreate(pixelData, width, height,
519
- 8, bytesPerRow, colorSpace,
520
- kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
521
-
547
+ CGContextRef context = CGBitmapContextCreate(
548
+ pixelData, width, height, 8, bytesPerRow, colorSpace,
549
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
550
+
522
551
  if (!context) {
523
552
  CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
524
553
  CVPixelBufferRelease(pixelBuffer);
525
554
  CGColorSpaceRelease(colorSpace);
526
555
  return NULL;
527
556
  }
528
-
557
+
529
558
  CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage);
530
-
559
+
531
560
  CGContextRelease(context);
532
561
  CGColorSpaceRelease(colorSpace);
533
562
  CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
534
-
563
+
535
564
  return pixelBuffer;
536
565
  }
537
566
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byteplus/react-native-live-push",
3
- "version": "1.1.3-rc.2",
3
+ "version": "1.1.3-rc.3",
4
4
  "peerDependencies": {
5
5
  "react": "*",
6
6
  "react-native": "*"