@volcengine/react-native-live-pull 1.5.2-rc.0 → 1.5.2-rc.2

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.
@@ -32,8 +32,17 @@
32
32
  }
33
33
 
34
34
  - (NSDictionary *)callApiSync:(NSDictionary *)args {
35
- [self newApiEngine];
36
- return [self.volcApiEngine callApi:args];
35
+ __block NSDictionary *result = nil;
36
+ void (^work)(void) = ^{
37
+ [self newApiEngine];
38
+ result = [self.volcApiEngine callApi:args];
39
+ };
40
+ if ([NSThread isMainThread]) {
41
+ work();
42
+ } else {
43
+ dispatch_sync(dispatch_get_main_queue(), work);
44
+ }
45
+ return result;
37
46
  }
38
47
 
39
48
  //callback 是OC的回调函数,外层需要进一步封装,接收一个NSDictionary类型的参数
@@ -44,22 +44,26 @@
44
44
  }
45
45
 
46
46
  - (void) insertSubview:(UIView *)view atIndex:(NSInteger)index {
47
- [super insertSubview:view atIndex:index];
48
- // 不需要在这里设置约束
47
+ // NSLog(@"insert playview, self bounds=%f x %f", self.bounds.size.width, self.bounds.size.height);
48
+ // NSLog(@"insert playview, view frame=%f x %f", view.frame.size.width, view.frame.size.height);
49
+ [super insertSubview:view atIndex:index];
50
+ [self setSubViewLayout:view];
49
51
  }
50
52
 
51
53
  - (void) addSubview:(UIView *)view {
52
- [super addSubview:view];
54
+ [super addSubview:view];
55
+ [self setSubViewLayout:view];
53
56
  }
54
57
 
55
- - (void)layoutSubviews {
56
- [super layoutSubviews];
57
- // 遍历子视图,强制对齐 frame
58
- for (UIView *subview in self.subviews) {
59
- if (!CGRectEqualToRect(subview.frame, self.bounds)) {
60
- subview.frame = self.bounds;
61
- }
62
- }
58
+ // 设置 Auto Layout,确保 subView 始终匹配 view 尺寸
59
+ - (void) setSubViewLayout:(UIView *)view {
60
+ view.translatesAutoresizingMaskIntoConstraints = NO;
61
+ [NSLayoutConstraint activateConstraints:@[
62
+ [view.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
63
+ [view.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
64
+ [view.topAnchor constraintEqualToAnchor:self.topAnchor],
65
+ [view.bottomAnchor constraintEqualToAnchor:self.bottomAnchor]
66
+ ]];
63
67
  }
64
68
 
65
- @end
69
+ @end
@@ -52,11 +52,17 @@ NSString *const kObserverKey = @"pip-observer";
52
52
  if (@available(iOS 14.2, *)) {
53
53
  _canStartPictureInPictureAutomaticallyFromInline = NO;
54
54
  }
55
+ // 监听从通知中心/后台返回活跃状态
56
+ [[NSNotificationCenter defaultCenter] addObserver:self
57
+ selector:@selector(handleAppDidBecomeActive)
58
+ name:UIApplicationDidBecomeActiveNotification
59
+ object:nil];
55
60
  }
56
61
  return self;
57
62
  }
58
63
 
59
64
  - (void)dealloc {
65
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
60
66
  [self disableVideoFrameObserver];
61
67
  [self stopPlaybackStateTimer];
62
68
 
@@ -68,6 +74,31 @@ NSString *const kObserverKey = @"pip-observer";
68
74
  [[VeLivePlayerMultiObserver sharedInstance] removeObserver:kObserverKey];
69
75
  }
70
76
 
77
+ - (void)handleAppDidBecomeActive {
78
+
79
+ if (self.pipController && [self.pipController pictureInPictureController]) {
80
+ // 只有在 PIP 开启状态下才需要重连,避免干扰正常播放
81
+ AVPictureInPictureController *controller =
82
+ [self.pipController pictureInPictureController];
83
+ if (controller.isPictureInPictureActive) {
84
+ __weak typeof(self) weakSelf = self;
85
+ dispatch_async(dispatch_get_main_queue(), ^{
86
+ __strong typeof(weakSelf) strongSelf = weakSelf;
87
+ if (!strongSelf) return;
88
+ // 强制重新绑定 ContentView。
89
+ // 这会诱导底层重新创建 IOSurface,修复内核日志中的 SID: 0x0 报错。
90
+ [strongSelf.pipController setContentView:strongSelf.contentView completion:^{
91
+ __strong typeof(weakSelf) strongSelf = weakSelf;
92
+ if (!strongSelf) return;
93
+ // 刷新播放状态,确保画面立即同步
94
+ [[strongSelf.pipController pictureInPictureController] invalidatePlaybackState];
95
+ NSLog(@"PIP: App active, re-bound Surface to fix potential corruption.");
96
+ }];
97
+ });
98
+ }
99
+ }
100
+ }
101
+
71
102
  // Start playback state refresh timer
72
103
  - (void)startPlaybackStateTimer {
73
104
  [self stopPlaybackStateTimer];
@@ -245,7 +276,7 @@ NSString *const kObserverKey = @"pip-observer";
245
276
  self.enableVideoObserver = YES;
246
277
  [self.player
247
278
  enableVideoFrameObserver:YES
248
- pixelFormat:VeLivePlayerPixelFormatBGRA32
279
+ pixelFormat:VeLivePlayerPixelFormatNV12
249
280
  bufferType:VeLivePlayerVideoBufferTypeSampleBuffer];
250
281
  [[VeLivePlayerMultiObserver sharedInstance] removeObserver:kObserverKey];
251
282
  [[VeLivePlayerMultiObserver sharedInstance] addObserver:kObserverKey
@@ -372,6 +403,20 @@ NSString *const kObserverKey = @"pip-observer";
372
403
  - (void)onRenderVideoFrame:(TVLManager *_Nonnull)player
373
404
  videoFrame:(VeLivePlayerVideoFrame *_Nonnull)videoFrame {
374
405
  @autoreleasepool {
406
+ UIApplicationState state = [UIApplication sharedApplication].applicationState;
407
+
408
+ // 【核心修正】
409
+ // 1. 如果是 Active (前台),正常推流。
410
+ // 2. 如果是 Background (正常画中画/后台),正常推流。
411
+ // 3. 【拦截】只有当状态是 Inactive 时:
412
+ // 这通常对应“下拉通知中心”、“拉下控制中心”或“系统弹窗”遮挡。
413
+ // 此时日志中的 SID: 0x0 报错最集中,必须拦截推流以保护内核句柄。
414
+ NSLog(@"PIP: Application state is %ld", (long)state);
415
+ if (state == UIApplicationStateInactive) {
416
+ // 如果正在画中画过程中,且 App 处于非活跃(被遮挡)状态,暂时丢弃这一帧
417
+ return;
418
+ }
419
+
375
420
  // Ensure pipController exists and is valid, avoid processing buffer during
376
421
  // destruction
377
422
  if (!self.pipController || !self.enableVideoObserver) {
@@ -470,4 +515,4 @@ NSString *const kObserverKey = @"pip-observer";
470
515
  }
471
516
  }
472
517
 
473
- @end
518
+ @end
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volcengine/react-native-live-pull",
3
- "version": "1.5.2-rc.0",
3
+ "version": "1.5.2-rc.2",
4
4
  "peerDependencies": {
5
5
  "react": "*",
6
6
  "react-native": "*"