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

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.
@@ -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,32 @@ 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
+ @"alpha" : viewInfo[@"alpha"] ?: @(1.0),
154
+ @"zOrder" : viewInfo[@"zOrder"] ?: @(1),
155
+ @"renderMode" : viewInfo[@"renderMode"] ?: @(0),
156
+ @"streamId" : @(videoStreamId)
150
157
  };
151
-
152
- VeLiveStreamMixDescription *description = [[VeLiveStreamMixDescription alloc] init];
158
+
159
+ VeLiveStreamMixDescription *description =
160
+ [[VeLiveStreamMixDescription alloc] init];
153
161
  VeLiveMixVideoLayout *videoLayout = [[VeLiveMixVideoLayout alloc] init];
154
162
  videoLayout.streamId = videoStreamId;
155
163
  videoLayout.x = [viewInfo[@"x"] floatValue];
@@ -157,19 +165,33 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
157
165
  videoLayout.width = [viewInfo[@"width"] floatValue];
158
166
  videoLayout.height = [viewInfo[@"height"] floatValue];
159
167
  videoLayout.zOrder = [viewInfo[@"zOrder"] intValue];
168
+ videoLayout.alpha = [viewInfo[@"alpha"] floatValue] ?: 1.0;
160
169
  videoLayout.renderMode = [viewInfo[@"renderMode"] intValue];
161
- description.mixVideoStreams = @[videoLayout];
170
+ description.mixVideoStreams = @[ videoLayout ];
162
171
  [self.pusher.getMixerManager updateStreamMixDescription:description];
163
-
172
+
164
173
  [self.mixedViewLayout setObject:layout forKey:viewId];
165
174
  [self.viewIdToStreamId setObject:@(videoStreamId) forKey:viewId];
166
-
175
+
167
176
  if ([view isKindOfClass:[VeLiveMixerUIView class]]) {
168
177
  [VeLiveMixerHelper setupCallbackForMixerView:view streamId:videoStreamId];
178
+
179
+ // 延迟执行捕获,确保视图布局完成
180
+ dispatch_after(
181
+ dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)),
182
+ dispatch_get_main_queue(), ^{
183
+ @try {
184
+ if (view && view.bitmapCaptureCallback) {
185
+ [view performCaptureWithTrigger:@"addView"];
186
+ }
187
+ } @catch (NSException *exception) {
188
+ // Ignore
189
+ }
190
+ });
169
191
  } else {
170
192
  [self.pendingCallbacks setObject:@(videoStreamId) forKey:viewId];
171
193
  }
172
-
194
+
173
195
  return videoStreamId;
174
196
  } @catch (NSException *exception) {
175
197
  return -1;
@@ -182,35 +204,55 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
182
204
  if (!layout) {
183
205
  return NO;
184
206
  }
185
-
207
+
186
208
  NSNumber *streamIdNumber = [self.viewIdToStreamId objectForKey:viewId];
187
209
  int videoStreamId = [streamIdNumber intValue];
188
-
210
+
189
211
  NSMutableDictionary *updatedLayout = [layout mutableCopy];
190
212
  [updatedLayout setObject:(viewInfo[@"x"] ?: layout[@"x"]) forKey:@"x"];
191
213
  [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];
214
+ [updatedLayout setObject:(viewInfo[@"width"] ?: layout[@"width"])
215
+ forKey:@"width"];
216
+ [updatedLayout setObject:(viewInfo[@"height"] ?: layout[@"height"])
217
+ forKey:@"height"];
218
+ [updatedLayout setObject:(viewInfo[@"zOrder"] ?: layout[@"zOrder"])
219
+ forKey:@"zOrder"];
220
+ [updatedLayout setObject:(viewInfo[@"alpha"] ?: layout[@"alpha"])
221
+ forKey:@"alpha"];
222
+ [updatedLayout setObject:(viewInfo[@"renderMode"] ?: layout[@"renderMode"])
223
+ forKey:@"renderMode"];
224
+
225
+ VeLiveStreamMixDescription *description =
226
+ [[VeLiveStreamMixDescription alloc] init];
198
227
  VeLiveMixVideoLayout *videoLayout = [[VeLiveMixVideoLayout alloc] init];
199
228
  videoLayout.streamId = videoStreamId;
200
229
  videoLayout.x = [updatedLayout[@"x"] floatValue];
201
230
  videoLayout.y = [updatedLayout[@"y"] floatValue];
202
231
  videoLayout.width = [updatedLayout[@"width"] floatValue];
203
232
  videoLayout.height = [updatedLayout[@"height"] floatValue];
233
+ videoLayout.alpha = [updatedLayout[@"alpha"] floatValue];
204
234
  videoLayout.zOrder = [updatedLayout[@"zOrder"] intValue];
205
235
  videoLayout.renderMode = [updatedLayout[@"renderMode"] intValue];
206
- description.mixVideoStreams = @[videoLayout];
236
+ description.mixVideoStreams = @[ videoLayout ];
207
237
  [self.pusher.getMixerManager updateStreamMixDescription:description];
208
-
238
+
209
239
  [self.mixedViewLayout setObject:updatedLayout forKey:viewId];
210
-
211
- VeLiveMixerUIView *mixerView = [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
212
- [mixerView performCaptureWithTrigger:@"update"];
213
-
240
+
241
+ // 延迟执行捕获,确保属性更新完成
242
+ VeLiveMixerUIView *mixerView =
243
+ [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
244
+ if ([mixerView isKindOfClass:[VeLiveMixerUIView class]]) {
245
+ dispatch_after(
246
+ dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)),
247
+ dispatch_get_main_queue(), ^{
248
+ @try {
249
+ [mixerView performCaptureWithTrigger:@"update"];
250
+ } @catch (NSException *exception) {
251
+ // Ignore
252
+ }
253
+ });
254
+ }
255
+
214
256
  return YES;
215
257
  } @catch (NSException *exception) {
216
258
  return NO;
@@ -223,26 +265,27 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
223
265
  if (!layout) {
224
266
  return NO;
225
267
  }
226
-
268
+
227
269
  NSNumber *streamIdNumber = [self.viewIdToStreamId objectForKey:viewId];
228
270
  if (streamIdNumber) {
229
271
  int streamId = [streamIdNumber intValue];
230
272
  [self.pusher.getMixerManager removeVideoStream:streamId];
231
-
273
+
232
274
  NSString *callbackKey = [NSString stringWithFormat:@"%d", streamId];
233
275
  [self.callbacks removeObjectForKey:callbackKey];
234
276
  }
235
-
277
+
236
278
  [self.viewIdToStreamId removeObjectForKey:viewId];
237
279
  [self.pendingCallbacks removeObjectForKey:viewId];
238
-
239
- VeLiveMixerUIView *view = [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
280
+
281
+ VeLiveMixerUIView *view =
282
+ [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
240
283
  if ([view isKindOfClass:[VeLiveMixerUIView class]]) {
241
284
  view.bitmapCaptureCallback = nil;
242
285
  }
243
-
286
+
244
287
  [self.mixedViewLayout removeObjectForKey:viewId];
245
-
288
+
246
289
  return YES;
247
290
  } @catch (NSException *exception) {
248
291
  return NO;
@@ -250,7 +293,8 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
250
293
  }
251
294
 
252
295
  - (void)captureView:(NSString *)viewId {
253
- VeLiveMixerUIView *view = [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
296
+ VeLiveMixerUIView *view =
297
+ [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
254
298
  if ([view isKindOfClass:[VeLiveMixerUIView class]]) {
255
299
  [view performCaptureWithTrigger:@"manual"];
256
300
  }
@@ -258,55 +302,64 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
258
302
 
259
303
  #pragma mark - Static Methods
260
304
 
261
- + (void)setupCallbackForMixerView:(VeLiveMixerUIView *)mixerView streamId:(int)streamId {
305
+ + (void)setupCallbackForMixerView:(VeLiveMixerUIView *)mixerView
306
+ streamId:(int)streamId {
262
307
  if (mixerView == nil) {
263
308
  return;
264
309
  }
265
-
310
+
266
311
  VeLiveMixerHelper *instance = [VeLiveMixerHelper findActiveMixerManager];
267
312
  if (!instance) {
268
313
  return;
269
314
  }
270
-
271
- VeLiveMixerBitmapCallback *callback = [[VeLiveMixerBitmapCallback alloc] initWithStreamId:streamId];
272
-
315
+
316
+ VeLiveMixerBitmapCallback *callback =
317
+ [[VeLiveMixerBitmapCallback alloc] initWithStreamId:streamId];
318
+
273
319
  NSString *callbackKey = [NSString stringWithFormat:@"%d", streamId];
274
320
  [instance.callbacks setObject:callback forKey:callbackKey];
275
-
321
+
276
322
  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];
323
+
324
+ dispatch_after(
325
+ dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)),
326
+ dispatch_get_main_queue(), ^{
327
+ @try {
328
+ if (mixerView && mixerView.bitmapCaptureCallback) {
329
+ VeLiveMixerHelper *instance =
330
+ [VeLiveMixerHelper findActiveMixerManager];
331
+ if (instance && instance.pusher) {
332
+ @try {
333
+ NSString *viewId = mixerView.viewId;
334
+ NSDictionary *layout =
335
+ [instance.mixedViewLayout objectForKey:viewId];
336
+ if (layout) {
337
+ VeLiveStreamMixDescription *description =
338
+ [[VeLiveStreamMixDescription alloc] init];
339
+ VeLiveMixVideoLayout *videoLayout =
340
+ [[VeLiveMixVideoLayout alloc] init];
341
+ videoLayout.streamId = streamId;
342
+ videoLayout.x = [layout[@"x"] floatValue];
343
+ videoLayout.y = [layout[@"y"] floatValue];
344
+ videoLayout.width = [layout[@"width"] floatValue];
345
+ videoLayout.height = [layout[@"height"] floatValue];
346
+ videoLayout.zOrder = [layout[@"zOrder"] intValue];
347
+ videoLayout.renderMode = [layout[@"renderMode"] intValue];
348
+ description.mixVideoStreams = @[ videoLayout ];
349
+ [instance.pusher.getMixerManager
350
+ updateStreamMixDescription:description];
351
+ }
352
+ } @catch (NSException *e) {
353
+ // Ignore
354
+ }
298
355
  }
299
- } @catch (NSException *e) {
300
- // Ignore
356
+
357
+ [mixerView performCaptureWithTrigger:@"update"];
301
358
  }
359
+ } @catch (NSException *exception) {
360
+ // Ignore
302
361
  }
303
-
304
- [mixerView performCaptureWithTrigger:@"update"];
305
- }
306
- } @catch (NSException *exception) {
307
- // Ignore
308
- }
309
- });
362
+ });
310
363
  }
311
364
 
312
365
  + (void)sendBitmapToMixerStatic:(int)streamId bitmap:(UIImage *)bitmap {
@@ -320,15 +373,18 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
320
373
  return currentInstance;
321
374
  }
322
375
 
323
- + (void)onViewReady:(NSString *)viewId mixerView:(VeLiveMixerUIView *)mixerView {
376
+ + (void)onViewReady:(NSString *)viewId
377
+ mixerView:(VeLiveMixerUIView *)mixerView {
324
378
  @try {
325
379
  VeLiveMixerHelper *instance = [VeLiveMixerHelper findActiveMixerManager];
326
380
  if (instance != nil) {
327
- NSNumber *streamIdNumber = [instance.pendingCallbacks objectForKey:viewId];
381
+ NSNumber *streamIdNumber =
382
+ [instance.pendingCallbacks objectForKey:viewId];
328
383
  if (streamIdNumber != nil) {
329
384
  int streamId = [streamIdNumber intValue];
330
385
  [instance.pendingCallbacks removeObjectForKey:viewId];
331
- [VeLiveMixerHelper setupCallbackForMixerView:mixerView streamId:streamId];
386
+ [VeLiveMixerHelper setupCallbackForMixerView:mixerView
387
+ streamId:streamId];
332
388
  }
333
389
  }
334
390
  } @catch (NSException *exception) {
@@ -338,36 +394,42 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
338
394
 
339
395
  - (void)cleanup {
340
396
  [self stopMemoryMonitoring];
341
-
397
+
342
398
  for (NSString *viewId in self.mixedViewLayout.allKeys) {
343
- VeLiveMixerUIView *view = [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
399
+ VeLiveMixerUIView *view =
400
+ [[VeLiveMixerHelper cachedMixedViews] objectForKey:viewId];
344
401
  if ([view isKindOfClass:[VeLiveMixerUIView class]]) {
345
402
  view.bitmapCaptureCallback = nil;
346
403
  }
347
404
  }
348
-
405
+
349
406
  [self.mixedViewLayout removeAllObjects];
350
407
  [self.pendingCallbacks removeAllObjects];
351
408
  [self.callbacks removeAllObjects];
352
-
409
+
353
410
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
354
411
  @autoreleasepool {
355
412
  [[NSURLCache sharedURLCache] removeAllCachedResponses];
356
413
  [[NSURLCache sharedURLCache] setMemoryCapacity:0];
357
414
  [[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
- });
415
+
416
+ [[NSNotificationCenter defaultCenter]
417
+ postNotificationName:UIApplicationDidReceiveMemoryWarningNotification
418
+ object:nil];
419
+
420
+ dispatch_after(
421
+ dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)),
422
+ dispatch_get_main_queue(),
423
+ ^{
424
+ // Final cleanup completed
425
+ });
364
426
  }
365
427
  });
366
428
  }
367
429
 
368
430
  - (void)dealloc {
369
431
  [self cleanup];
370
-
432
+
371
433
  if (currentInstance == self) {
372
434
  currentInstance = nil;
373
435
  }
@@ -376,11 +438,12 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
376
438
  #pragma mark - Memory Monitoring
377
439
 
378
440
  - (void)startMemoryMonitoring {
379
- self.memoryMonitorTimer = [NSTimer scheduledTimerWithTimeInterval:30.0
380
- target:self
381
- selector:@selector(checkMemoryUsage)
382
- userInfo:nil
383
- repeats:YES];
441
+ self.memoryMonitorTimer =
442
+ [NSTimer scheduledTimerWithTimeInterval:30.0
443
+ target:self
444
+ selector:@selector(checkMemoryUsage)
445
+ userInfo:nil
446
+ repeats:YES];
384
447
  }
385
448
 
386
449
  - (void)stopMemoryMonitoring {
@@ -394,11 +457,12 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
394
457
  @autoreleasepool {
395
458
  struct task_basic_info info;
396
459
  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
-
460
+ kern_return_t kerr =
461
+ task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
462
+
399
463
  if (kerr == KERN_SUCCESS) {
400
464
  double memoryUsageMB = info.resident_size / 1024.0 / 1024.0;
401
-
465
+
402
466
  if (memoryUsageMB > 200.0) {
403
467
  [self performMemoryCleanup];
404
468
  }
@@ -415,20 +479,24 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
415
479
  if ([view isKindOfClass:[VeLiveMixerUIView class]]) {
416
480
  if ([view.captureMode isEqualToString:@"realtime"]) {
417
481
  [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
- });
482
+
483
+ dispatch_after(
484
+ dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)),
485
+ dispatch_get_main_queue(), ^{
486
+ if (view && [cachedViews objectForKey:viewId] == view) {
487
+ [view startCapture];
488
+ }
489
+ });
424
490
  }
425
491
  }
426
492
  }
427
-
493
+
428
494
  [[NSURLCache sharedURLCache] removeAllCachedResponses];
429
495
  [[NSURLCache sharedURLCache] setMemoryCapacity:5 * 1024 * 1024];
430
-
431
- [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification object:nil];
496
+
497
+ [[NSNotificationCenter defaultCenter]
498
+ postNotificationName:UIApplicationDidReceiveMemoryWarningNotification
499
+ object:nil];
432
500
  }
433
501
  });
434
502
  }
@@ -440,34 +508,26 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
440
508
  if (!self.pusher || !bitmap) {
441
509
  return;
442
510
  }
443
-
511
+
444
512
  CVPixelBufferRef pixelBuffer = NULL;
445
-
513
+
446
514
  @try {
447
515
  pixelBuffer = [self pixelBufferFromUIImage:bitmap];
448
516
  if (!pixelBuffer) {
449
517
  return;
450
518
  }
451
-
519
+
452
520
  VeLiveVideoFrame *videoFrame = [[VeLiveVideoFrame alloc] init];
453
521
  videoFrame.bufferType = VeLiveVideoBufferTypePixelBuffer;
454
522
  videoFrame.pts = CMTimeMakeWithSeconds(CACurrentMediaTime(), 1000000000);
455
523
  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
-
524
+
525
+ [[self.pusher getMixerManager] sendCustomVideoFrame:videoFrame
526
+ streamId:streamId];
527
+ CVPixelBufferRelease(pixelBuffer);
528
+
469
529
  pixelBuffer = NULL;
470
-
530
+
471
531
  } @catch (NSException *exception) {
472
532
  if (pixelBuffer) {
473
533
  CVPixelBufferRelease(pixelBuffer);
@@ -483,55 +543,53 @@ static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释
483
543
  if (!image) {
484
544
  return NULL;
485
545
  }
486
-
546
+
487
547
  CGImageRef cgImage = image.CGImage;
488
548
  if (!cgImage) {
489
549
  return NULL;
490
550
  }
491
-
551
+
492
552
  CGFloat width = CGImageGetWidth(cgImage);
493
553
  CGFloat height = CGImageGetHeight(cgImage);
494
-
554
+
495
555
  NSDictionary *options = @{
496
- (NSString *)kCVPixelBufferCGImageCompatibilityKey: @YES,
497
- (NSString *)kCVPixelBufferCGBitmapContextCompatibilityKey: @YES,
498
- (NSString *)kCVPixelBufferIOSurfacePropertiesKey: @{}
556
+ (NSString *)kCVPixelBufferCGImageCompatibilityKey : @YES,
557
+ (NSString *)kCVPixelBufferCGBitmapContextCompatibilityKey : @YES,
558
+ (NSString *)kCVPixelBufferIOSurfacePropertiesKey : @{}
499
559
  };
500
-
560
+
501
561
  CVPixelBufferRef pixelBuffer = NULL;
502
- CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
503
- width, height,
504
- kCVPixelFormatType_32BGRA,
505
- (__bridge CFDictionaryRef)options,
506
- &pixelBuffer);
507
-
562
+ CVReturn status = CVPixelBufferCreate(
563
+ kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA,
564
+ (__bridge CFDictionaryRef)options, &pixelBuffer);
565
+
508
566
  if (status != kCVReturnSuccess || !pixelBuffer) {
509
567
  return NULL;
510
568
  }
511
-
569
+
512
570
  CVPixelBufferLockBaseAddress(pixelBuffer, 0);
513
-
571
+
514
572
  void *pixelData = CVPixelBufferGetBaseAddress(pixelBuffer);
515
573
  size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);
516
-
574
+
517
575
  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
518
- CGContextRef context = CGBitmapContextCreate(pixelData, width, height,
519
- 8, bytesPerRow, colorSpace,
520
- kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
521
-
576
+ CGContextRef context = CGBitmapContextCreate(
577
+ pixelData, width, height, 8, bytesPerRow, colorSpace,
578
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
579
+
522
580
  if (!context) {
523
581
  CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
524
582
  CVPixelBufferRelease(pixelBuffer);
525
583
  CGColorSpaceRelease(colorSpace);
526
584
  return NULL;
527
585
  }
528
-
586
+
529
587
  CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage);
530
-
588
+
531
589
  CGContextRelease(context);
532
590
  CGColorSpaceRelease(colorSpace);
533
591
  CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
534
-
592
+
535
593
  return pixelBuffer;
536
594
  }
537
595