@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.
- package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerManager.java +161 -141
- package/android/src/main/java/com/volcengine/velive/rn/push/mixer/MixerView.java +9 -1
- package/android/src/main/java/com/volcengine/velive/rn/push/mixer/TextureMgr.java +3 -3
- package/android/src/main/java/com/volcengine/velive/rn/push/mixer/YuvHelper.java +16 -5
- package/ios/VeLiveMixerHelper.m +222 -164
- package/ios/VeLiveMixerView.m +120 -112
- package/lib/commonjs/index.js +14 -1374
- package/lib/commonjs/typescript/core/keytype.d.ts +1 -0
- package/lib/module/index.js +15 -1375
- package/lib/module/typescript/core/keytype.d.ts +1 -0
- package/lib/typescript/core/keytype.d.ts +1 -0
- package/package.json +1 -1
package/ios/VeLiveMixerHelper.m
CHANGED
|
@@ -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)
|
|
26
|
-
|
|
27
|
-
@property(nonatomic, strong)
|
|
28
|
-
|
|
29
|
-
@property
|
|
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
|
|
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 =
|
|
47
|
+
static NSMutableDictionary<NSString *, VeLiveMixerUIView *> *_cachedMixedViews =
|
|
48
|
+
nil;
|
|
44
49
|
static VeLiveMixerHelper *currentInstance = nil; // 强引用,防止被ARC释放
|
|
45
50
|
|
|
46
51
|
+ (NSMutableDictionary<NSString *, VeLiveMixerUIView *> *)cachedMixedViews {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
if (!_cachedMixedViews) {
|
|
53
|
+
_cachedMixedViews = [[NSMutableDictionary alloc] init];
|
|
54
|
+
}
|
|
55
|
+
return _cachedMixedViews;
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
+ (void)setCachedMixedViews:
|
|
54
|
-
|
|
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
|
-
@"
|
|
148
|
-
@"
|
|
149
|
-
@"
|
|
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 =
|
|
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"])
|
|
193
|
-
|
|
194
|
-
[updatedLayout setObject:(viewInfo[@"
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
|
|
212
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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
|
-
|
|
300
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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]
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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 =
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
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 =
|
|
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(
|
|
420
|
-
|
|
421
|
-
|
|
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]
|
|
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
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
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(
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
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(
|
|
519
|
-
|
|
520
|
-
|
|
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
|
|