@volcengine/react-native-live-pull 1.0.3-rc.0 → 1.1.1-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 (25) hide show
  1. package/android/src/main/AndroidManifest.xml +7 -1
  2. package/android/src/main/AndroidManifestNew.xml +15 -1
  3. package/android/src/main/java/com/volcengine/velive/rn/pull/VolcLiveModule.java +28 -20
  4. package/android/src/main/java/com/volcengine/velive/rn/pull/VolcView.java +7 -8
  5. package/android/src/main/java/com/volcengine/velive/rn/pull/pictureInpicture/FloatingWindowHelper.java +224 -0
  6. package/android/src/main/java/com/volcengine/velive/rn/pull/pictureInpicture/FloatingWindowService.java +171 -0
  7. package/android/src/main/java/com/volcengine/velive/rn/pull/pictureInpicture/IFloatingWindowHelper.java +80 -0
  8. package/android/src/main/java/com/volcengine/velive/rn/pull/pictureInpicture/PictureInPictureManager.java +280 -0
  9. package/android/src/main/java/com/volcengine/velive/rn/pull/pictureInpicture/VeLiveRefManager.java +119 -0
  10. package/android/src/main/res/drawable/button_close.xml +14 -0
  11. package/android/src/main/res/layout/floating_window_layout.xml +19 -0
  12. package/ios/VeLivePlayerMultiObserver.h +54 -0
  13. package/ios/VeLivePlayerMultiObserver.m +324 -0
  14. package/ios/pictureInpicture/PictureInPictureManager.h +29 -0
  15. package/ios/pictureInpicture/PictureInPictureManager.m +274 -0
  16. package/ios/pictureInpicture/VeLivePictureInPictureController.h +207 -0
  17. package/ios/pictureInpicture/VeLivePictureInPictureController.m +3393 -0
  18. package/lib/commonjs/index.js +524 -8
  19. package/lib/module/index.js +524 -8
  20. package/lib/typescript/core/api.d.ts +88 -1
  21. package/lib/typescript/core/callback.d.ts +52 -0
  22. package/lib/typescript/platforms/android/extends.d.ts +1 -1
  23. package/lib/typescript/platforms/android/pictureInpicture.d.ts +26 -0
  24. package/lib/typescript/platforms/ios/pictureInpicture.d.ts +32 -0
  25. package/package.json +1 -1
@@ -0,0 +1,324 @@
1
+ #import "VeLivePlayerMultiObserver.h"
2
+ #import "TTSDKFramework/TVLManager.h"
3
+
4
+ @interface VeLivePlayerMultiObserver ()
5
+ @property(nonatomic, strong) NSMutableDictionary *observerDict;
6
+ @property(nonatomic, strong) dispatch_queue_t observerQueue;
7
+ @property(nonatomic, strong) TVLManager *player;
8
+ @end
9
+
10
+ @implementation VeLivePlayerMultiObserver
11
+
12
+ // 单例实现
13
+ + (instancetype)sharedInstance {
14
+ static VeLivePlayerMultiObserver *instance = nil;
15
+ static dispatch_once_t onceToken;
16
+ dispatch_once(&onceToken, ^{
17
+ instance = [[self alloc] init];
18
+ });
19
+ return instance;
20
+ }
21
+
22
+ + (instancetype)getInstance {
23
+ return [self sharedInstance];
24
+ }
25
+
26
+ // 初始化方法
27
+ - (instancetype)init {
28
+ self = [super init];
29
+ if (self) {
30
+ _observerDict = [NSMutableDictionary dictionary];
31
+ _observerQueue = dispatch_queue_create("com.velive.player.multiobserver",
32
+ DISPATCH_QUEUE_SERIAL);
33
+ }
34
+ return self;
35
+ }
36
+
37
+ - (void)setupPlayer:(TVLManager *)player {
38
+ if(self.player) {
39
+ [self clearObservers];
40
+ }
41
+ self.player = player;
42
+ [player setObserver:self];
43
+ }
44
+
45
+ // 添加观察者到字典中
46
+ - (void)addObserver:(NSString *)observerId
47
+ observer:(id<VeLivePlayerObserver>)observer {
48
+ if (!observer || !observerId) {
49
+ return;
50
+ }
51
+
52
+ dispatch_sync(self.observerQueue, ^{
53
+ [self.observerDict setObject:observer forKey:observerId];
54
+ });
55
+ }
56
+
57
+ // 从字典中移除观察者
58
+ - (void)removeObserver:(NSString *)observerId {
59
+ if (!observerId) {
60
+ return;
61
+ }
62
+
63
+ dispatch_sync(self.observerQueue, ^{
64
+ [self.observerDict removeObjectForKey:observerId];
65
+ });
66
+ }
67
+
68
+ // 获取所有观察者
69
+ - (NSArray *)getObservers {
70
+ __block NSArray *result = nil;
71
+ dispatch_sync(self.observerQueue, ^{
72
+ result = [self.observerDict allValues];
73
+ });
74
+ return result;
75
+ }
76
+
77
+ // 清空所有观察者
78
+ - (void)clearObservers {
79
+ dispatch_sync(self.observerQueue, ^{
80
+ [self.observerDict removeAllObjects];
81
+ });
82
+ }
83
+
84
+ #pragma mark - VeLivePlayerObserver 方法实现
85
+
86
+ // 直接实现所有 VeLivePlayerObserver 协议方法,而不是依赖消息转发
87
+
88
+ - (void)onError:(TVLManager *)player error:(VeLivePlayerError *)error {
89
+ NSArray *observers = [self getObservers];
90
+ for (id<VeLivePlayerObserver> observer in observers) {
91
+ if ([observer respondsToSelector:@selector(onError:error:)]) {
92
+ [observer onError:player error:error];
93
+ }
94
+ }
95
+ }
96
+
97
+ - (void)onFirstVideoFrameRender:(TVLManager *)player
98
+ isFirstFrame:(BOOL)isFirstFrame {
99
+ NSArray *observers = [self getObservers];
100
+ for (id<VeLivePlayerObserver> observer in observers) {
101
+ if ([observer respondsToSelector:@selector(onFirstVideoFrameRender:
102
+ isFirstFrame:)]) {
103
+ [observer onFirstVideoFrameRender:player isFirstFrame:isFirstFrame];
104
+ }
105
+ }
106
+ }
107
+
108
+ - (void)onFirstAudioFrameRender:(TVLManager *)player
109
+ isFirstFrame:(BOOL)isFirstFrame {
110
+ NSArray *observers = [self getObservers];
111
+ for (id<VeLivePlayerObserver> observer in observers) {
112
+ if ([observer respondsToSelector:@selector(onFirstAudioFrameRender:
113
+ isFirstFrame:)]) {
114
+ [observer onFirstAudioFrameRender:player isFirstFrame:isFirstFrame];
115
+ }
116
+ }
117
+ }
118
+
119
+ - (void)onStallStart:(TVLManager *)player {
120
+ NSArray *observers = [self getObservers];
121
+ for (id<VeLivePlayerObserver> observer in observers) {
122
+ if ([observer respondsToSelector:@selector(onStallStart:)]) {
123
+ [observer onStallStart:player];
124
+ }
125
+ }
126
+ }
127
+
128
+ - (void)onStallEnd:(TVLManager *)player {
129
+ NSArray *observers = [self getObservers];
130
+ for (id<VeLivePlayerObserver> observer in observers) {
131
+ if ([observer respondsToSelector:@selector(onStallEnd:)]) {
132
+ [observer onStallEnd:player];
133
+ }
134
+ }
135
+ }
136
+
137
+ - (void)onVideoRenderStall:(TVLManager *)player stallTime:(int64_t)stallTime {
138
+ NSArray *observers = [self getObservers];
139
+ for (id<VeLivePlayerObserver> observer in observers) {
140
+ if ([observer respondsToSelector:@selector(onVideoRenderStall:
141
+ stallTime:)]) {
142
+ [observer onVideoRenderStall:player stallTime:stallTime];
143
+ }
144
+ }
145
+ }
146
+
147
+ - (void)onAudioRenderStall:(TVLManager *)player stallTime:(int64_t)stallTime {
148
+ NSArray *observers = [self getObservers];
149
+ for (id<VeLivePlayerObserver> observer in observers) {
150
+ if ([observer respondsToSelector:@selector(onAudioRenderStall:
151
+ stallTime:)]) {
152
+ [observer onAudioRenderStall:player stallTime:stallTime];
153
+ }
154
+ }
155
+ }
156
+
157
+ - (void)onResolutionSwitch:(TVLManager *)player
158
+ resolution:(VeLivePlayerResolution)resolution
159
+ error:(VeLivePlayerError *)error
160
+ reason:(VeLivePlayerResolutionSwitchReason)reason {
161
+ NSArray *observers = [self getObservers];
162
+ for (id<VeLivePlayerObserver> observer in observers) {
163
+ if ([observer respondsToSelector:@selector
164
+ (onResolutionSwitch:resolution:error:reason:)]) {
165
+ [observer onResolutionSwitch:player
166
+ resolution:resolution
167
+ error:error
168
+ reason:reason];
169
+ }
170
+ }
171
+ }
172
+
173
+ - (void)onVideoSizeChanged:(TVLManager *)player
174
+ width:(int)width
175
+ height:(int)height {
176
+ NSArray *observers = [self getObservers];
177
+ for (id<VeLivePlayerObserver> observer in observers) {
178
+ if ([observer respondsToSelector:@selector(onVideoSizeChanged:
179
+ width:height:)]) {
180
+ [observer onVideoSizeChanged:player width:width height:height];
181
+ }
182
+ }
183
+ }
184
+
185
+ - (void)onReceiveSeiMessage:(TVLManager *)player message:(NSString *)message {
186
+ NSArray *observers = [self getObservers];
187
+ for (id<VeLivePlayerObserver> observer in observers) {
188
+ if ([observer respondsToSelector:@selector(onReceiveSeiMessage:message:)]) {
189
+ [observer onReceiveSeiMessage:player message:message];
190
+ }
191
+ }
192
+ }
193
+
194
+ - (void)onMainBackupSwitch:(TVLManager *)player
195
+ streamType:(VeLivePlayerStreamType)streamType
196
+ error:(VeLivePlayerError *)error {
197
+ NSArray *observers = [self getObservers];
198
+ for (id<VeLivePlayerObserver> observer in observers) {
199
+ if ([observer respondsToSelector:@selector(onMainBackupSwitch:
200
+ streamType:error:)]) {
201
+ [observer onMainBackupSwitch:player streamType:streamType error:error];
202
+ }
203
+ }
204
+ }
205
+
206
+ - (void)onPlayerStatusUpdate:(TVLManager *)player
207
+ status:(VeLivePlayerStatus)status {
208
+ NSArray *observers = [self getObservers];
209
+ for (id<VeLivePlayerObserver> observer in observers) {
210
+ if ([observer respondsToSelector:@selector(onPlayerStatusUpdate:status:)]) {
211
+ [observer onPlayerStatusUpdate:player status:status];
212
+ }
213
+ }
214
+ }
215
+
216
+ - (void)onStatistics:(TVLManager *)player
217
+ statistics:(VeLivePlayerStatistics *)statistics {
218
+ NSArray *observers = [self getObservers];
219
+ for (id<VeLivePlayerObserver> observer in observers) {
220
+ if ([observer respondsToSelector:@selector(onStatistics:statistics:)]) {
221
+ [observer onStatistics:player statistics:statistics];
222
+ }
223
+ }
224
+ }
225
+
226
+ - (void)onSnapshotComplete:(TVLManager *)player image:(UIImage *)image {
227
+ NSArray *observers = [self getObservers];
228
+ for (id<VeLivePlayerObserver> observer in observers) {
229
+ if ([observer respondsToSelector:@selector(onSnapshotComplete:image:)]) {
230
+ [observer onSnapshotComplete:player image:image];
231
+ }
232
+ }
233
+ }
234
+
235
+ - (void)onRenderVideoFrame:(TVLManager *)player
236
+ videoFrame:(VeLivePlayerVideoFrame *)videoFrame {
237
+ NSArray *observers = [self getObservers];
238
+ for (id<VeLivePlayerObserver> observer in observers) {
239
+ if ([observer respondsToSelector:@selector(onRenderVideoFrame:
240
+ videoFrame:)]) {
241
+ // 跳过 rn-observer,只转发给其他观察者(如 pip-observer)
242
+ NSString *observerId = nil;
243
+ for (NSString *key in self.observerDict) {
244
+ if ([self.observerDict objectForKey:key] == observer) {
245
+ observerId = key;
246
+ break;
247
+ }
248
+ }
249
+
250
+ // 如果观察者ID包含 "rn",则跳过帧处理
251
+ if (observerId && [observerId containsString:@"rn"]) {
252
+ continue;
253
+ }
254
+
255
+ [observer onRenderVideoFrame:player videoFrame:videoFrame];
256
+ }
257
+ }
258
+ }
259
+
260
+ - (void)onRenderAudioFrame:(TVLManager *)player
261
+ audioFrame:(VeLivePlayerAudioFrame *)audioFrame {
262
+ NSArray *observers = [self getObservers];
263
+ for (id<VeLivePlayerObserver> observer in observers) {
264
+ if ([observer respondsToSelector:@selector(onRenderAudioFrame:
265
+ audioFrame:)]) {
266
+ // 跳过 rn-observer,只转发给其他观察者
267
+ NSString *observerId = nil;
268
+ for (NSString *key in self.observerDict) {
269
+ if ([self.observerDict objectForKey:key] == observer) {
270
+ observerId = key;
271
+ break;
272
+ }
273
+ }
274
+
275
+ // 如果观察者ID包含 "rn",则跳过帧处理
276
+ if (observerId && [observerId containsString:@"rn"]) {
277
+ continue;
278
+ }
279
+
280
+ [observer onRenderAudioFrame:player audioFrame:audioFrame];
281
+ }
282
+ }
283
+ }
284
+
285
+ - (void)onStreamFailedOpenSuperResolution:(TVLManager *)player
286
+ error:(VeLivePlayerError *)error {
287
+ NSArray *observers = [self getObservers];
288
+ for (id<VeLivePlayerObserver> observer in observers) {
289
+ if ([observer respondsToSelector:@selector
290
+ (onStreamFailedOpenSuperResolution:error:)]) {
291
+ [observer onStreamFailedOpenSuperResolution:player error:error];
292
+ }
293
+ }
294
+ }
295
+
296
+ - (NSData *)getDrmResourceLoaderCertificateData:(TVLManager *)player {
297
+ NSArray *observers = [self getObservers];
298
+ for (id<VeLivePlayerObserver> observer in observers) {
299
+ if ([observer respondsToSelector:@selector
300
+ (getDrmResourceLoaderCertificateData:)]) {
301
+ NSData *data = [observer getDrmResourceLoaderCertificateData:player];
302
+ if (data) {
303
+ return data;
304
+ }
305
+ }
306
+ }
307
+ return nil;
308
+ }
309
+
310
+ - (NSString *)getDrmResourceLoaderLicenseUrl:(TVLManager *)player {
311
+ NSArray *observers = [self getObservers];
312
+ for (id<VeLivePlayerObserver> observer in observers) {
313
+ if ([observer
314
+ respondsToSelector:@selector(getDrmResourceLoaderLicenseUrl:)]) {
315
+ NSString *url = [observer getDrmResourceLoaderLicenseUrl:player];
316
+ if (url) {
317
+ return url;
318
+ }
319
+ }
320
+ }
321
+ return nil;
322
+ }
323
+
324
+ @end
@@ -0,0 +1,29 @@
1
+ #import <Foundation/Foundation.h>
2
+ @class TVLManager;
3
+ @class UIView;
4
+
5
+ @protocol VeLivePictureInPictureManagerListener <NSObject>
6
+ - (void)onStartPictureInPicture;
7
+ - (void)onStopPictureInPicture;
8
+ - (void)onClickPictureInPicture;
9
+ - (void)onError:(NSInteger)code extraData:(NSDictionary *)extraData;
10
+ @end
11
+
12
+ @interface VeLivePictureInPictureManager : NSObject
13
+
14
+ // Expose shared instance methods to RN
15
+ + (instancetype)sharedInstance;
16
+ + (instancetype)getInstance;
17
+
18
+ // Expose other methods that need to be called from RN
19
+ - (void)setupPlayer:(TVLManager *)player;
20
+ - (void)enablePictureInPicture;
21
+ - (void)disablePictureInPicture;
22
+ - (void)startPictureInPicture;
23
+ - (void)stopPictureInPicture;
24
+ - (void)destroyPictureInPicture;
25
+ - (BOOL)isPictureInPictureSupported;
26
+ - (void)setListener:(id<VeLivePictureInPictureManagerListener>)listener;
27
+
28
+
29
+ @end
@@ -0,0 +1,274 @@
1
+ #import "PictureInPictureManager.h"
2
+ #import "../VeLivePlayerMultiObserver.h"
3
+ #import "TTSDKFramework/TVLManager.h"
4
+ #import "VeLivePictureInPictureController.h"
5
+ #import <AVKit/AVKit.h>
6
+ #import <UIKit/UIKit.h>
7
+
8
+ @protocol VeLivePlayerObserver;
9
+ @protocol VeLivePictureInPictureDelegate;
10
+ @protocol VeLivePictureInPictureManagerListener;
11
+
12
+ // Add class extension to declare private properties instead of redefining
13
+ // interface
14
+ @interface VeLivePictureInPictureManager () <
15
+ VeLivePlayerObserver, VeLivePictureInPictureDelegate,
16
+ VeLivePictureInPictureManagerListener>
17
+ @property(nonatomic, strong) VeLivePictureInPictureController *pipController;
18
+ @property(nonatomic, assign) CGRect pipVideoFrame;
19
+ @property(nonatomic, assign) CGSize pipVideoSize;
20
+ @property(nonatomic, assign) BOOL enableVideoObserver;
21
+ @property(nonatomic, strong) TVLManager *player;
22
+ @property(nonatomic, weak) id<VeLivePictureInPictureManagerListener> listener;
23
+ @property(nonatomic, assign) BOOL pipAutoStart;
24
+ @end
25
+
26
+ NSString *const kObserverKey = @"pip-observer";
27
+
28
+ @implementation VeLivePictureInPictureManager
29
+
30
+ + (instancetype)sharedInstance {
31
+ static VeLivePictureInPictureManager *instance = nil;
32
+ static dispatch_once_t onceToken;
33
+ dispatch_once(&onceToken, ^{
34
+ instance = [[self alloc] init];
35
+ });
36
+ return instance;
37
+ }
38
+
39
+ + (instancetype)getInstance {
40
+ return [self sharedInstance];
41
+ }
42
+
43
+ - (void)setupPlayer:(TVLManager *)player {
44
+ if (self.player) {
45
+ [self destroyPictureInPicture];
46
+ }
47
+ self.player = player;
48
+
49
+ // Reset video frame observer status
50
+ self.enableVideoObserver = NO;
51
+ self.pipAutoStart = NO;
52
+ }
53
+
54
+ - (void)setupPictureInPicturePrepareCompletion:
55
+ (VELPipPrepareCompletionBlock)prepareCompletion {
56
+ if (!self.pipController) {
57
+ self.pipController = [[VeLivePictureInPictureController alloc]
58
+ initWithType:VeLivePictureInPictureTypeAuto
59
+ contentView:self.player.playerView];
60
+ [self setupPipVideoFrameAndSize];
61
+ self.pipController.delegate = self;
62
+ self.pipController.contentController = nil;
63
+ self.pipController.autoHideContentController = NO;
64
+ if (@available(iOS 14.0, *)) {
65
+ self.player.supportPictureInPictureMode = YES;
66
+ }
67
+ }
68
+ [self.pipController prepareWithCompletion:prepareCompletion];
69
+ }
70
+
71
+ - (void)setupPipVideoFrameAndSize {
72
+ if (!CGSizeEqualToSize(self.pipVideoSize, CGSizeZero)) {
73
+ [self.pipController setVideoSize:self.pipVideoSize];
74
+ }
75
+ if (!CGRectEqualToRect(self.pipVideoFrame, CGRectZero)) {
76
+ [self.pipController setVideoFrame:self.pipVideoFrame];
77
+ }
78
+ }
79
+
80
+ - (void)enableVideoFrameObserver {
81
+ NSLog(@"PIP: Enable video frame observer");
82
+ if (self.enableVideoObserver) {
83
+ // If already enabled, disable then re-enable to ensure the observer is
84
+ // re-registered
85
+ [self disableVideoFrameObserver];
86
+ }
87
+ self.enableVideoObserver = YES;
88
+ [self.player
89
+ enableVideoFrameObserver:YES
90
+ pixelFormat:VeLivePlayerPixelFormatBGRA32
91
+ bufferType:VeLivePlayerVideoBufferTypeSampleBuffer];
92
+ NSLog(@"PIP: Video frame observer enabled");
93
+ }
94
+
95
+ - (void)disableVideoFrameObserver {
96
+ NSLog(@"PIP: Disable video frame observer");
97
+ if (!self.enableVideoObserver) {
98
+ return;
99
+ }
100
+ self.enableVideoObserver = NO;
101
+ [self.player enableVideoFrameObserver:NO
102
+ pixelFormat:VeLivePlayerPixelFormatUnknown
103
+ bufferType:VeLivePlayerVideoBufferTypeUnknown];
104
+ NSLog(@"PIP: Video frame observer disabled");
105
+ }
106
+
107
+ - (void)startPictureInPicture {
108
+ NSLog(@"PIP: Start picture-in-picture");
109
+ [self enableVideoFrameObserver];
110
+
111
+ // Ensure observer is properly added
112
+ [[VeLivePlayerMultiObserver sharedInstance] removeObserver:kObserverKey];
113
+ [[VeLivePlayerMultiObserver sharedInstance] addObserver:kObserverKey
114
+ observer:self];
115
+
116
+ // Use main thread with delay to ensure state is updated
117
+ dispatch_async(dispatch_get_main_queue(), ^{
118
+ [self setupPictureInPicturePrepareCompletion:^(
119
+ VeLivePictureInPictureController *_Nonnull pipController,
120
+ NSError *_Nullable error) {
121
+ if (error != nil) {
122
+ NSLog(@"PIP: Failed to start picture-in-picture: %@", error);
123
+ return;
124
+ }
125
+ if (!self.player.isPlaying) {
126
+ NSLog(@"PIP: Please start playing before entering PIP mode");
127
+ return;
128
+ }
129
+ if (!self.pipController.canStartPictureInPicture) {
130
+ NSLog(@"PIP: Cannot start picture-in-picture now, please try again "
131
+ @"later");
132
+ return;
133
+ }
134
+ NSLog(@"PIP: Ready to start picture-in-picture");
135
+ [self.pipController startPictureInPicture];
136
+ }];
137
+ });
138
+ }
139
+
140
+ - (void)stopPictureInPicture {
141
+ [self disableVideoFrameObserver];
142
+ [[VeLivePlayerMultiObserver sharedInstance] removeObserver:kObserverKey];
143
+ [self.pipController stopPictureInPicture];
144
+ }
145
+
146
+ - (void)destroyPictureInPicture {
147
+ dispatch_async(dispatch_get_main_queue(), ^{
148
+ [self disableVideoFrameObserver];
149
+ [self.pipController destroyPictureInPicture];
150
+ [self setPipController:nil];
151
+ [[VeLivePlayerMultiObserver sharedInstance] removeObserver:kObserverKey];
152
+ self.player = nil;
153
+ });
154
+ }
155
+
156
+ - (BOOL)isPictureInPictureStarted {
157
+ return VeLivePictureInPictureController.isPictureInPictureStarted;
158
+ }
159
+
160
+ - (BOOL)isPictureInPictureSupported {
161
+ return [VeLivePictureInPictureController isPictureInPictureSupported];
162
+ }
163
+
164
+ - (void)enablePictureInPicture {
165
+ NSLog(@"PIP: Enable picture-in-picture");
166
+ self.pipAutoStart = YES;
167
+ // main thread
168
+ dispatch_async(dispatch_get_main_queue(), ^{
169
+ if (@available(iOS 14.2, *)) {
170
+ [self setupPictureInPicturePrepareCompletion:^(
171
+ VeLivePictureInPictureController *_Nonnull pipController,
172
+ NSError *_Nullable error) {
173
+ // Set in callback to ensure controller is ready
174
+ [pipController setCanStartPictureInPictureAutomaticallyFromInline:YES];
175
+ }];
176
+ }
177
+ });
178
+ }
179
+
180
+ - (void)disablePictureInPicture {
181
+ NSLog(@"PIP: Disable picture-in-picture");
182
+ self.pipAutoStart = NO;
183
+ if (!self.pipController) {
184
+ return;
185
+ }
186
+ dispatch_async(dispatch_get_main_queue(), ^{
187
+ if (@available(iOS 14.2, *)) {
188
+ [self.pipController
189
+ setCanStartPictureInPictureAutomaticallyFromInline:NO];
190
+ [self.pipController destroyPictureInPicture];
191
+ self.pipController = nil;
192
+ }
193
+ });
194
+ }
195
+
196
+ - (void)setListener:(id<VeLivePictureInPictureManagerListener>)listener {
197
+ _listener = listener;
198
+ }
199
+
200
+ // MARK: - VeLiveVideoFrameListener
201
+ - (void)onRenderVideoFrame:(TVLManager *_Nonnull)player
202
+ videoFrame:(VeLivePlayerVideoFrame *_Nonnull)videoFrame {
203
+ @autoreleasepool {
204
+ if (@available(iOS 15.0, *)) {
205
+ if (videoFrame.bufferType == VeLivePlayerVideoBufferTypePixelBuffer) {
206
+ [self.pipController enqueuePixelBuffer:videoFrame.pixelBuffer];
207
+ } else if (videoFrame.bufferType ==
208
+ VeLivePlayerVideoBufferTypeSampleBuffer) {
209
+ [self.pipController enqueueSampleBuffer:videoFrame.sampleBuffer];
210
+ }
211
+ }
212
+ }
213
+ }
214
+
215
+ - (void)onVideoSizeChanged:(TVLManager *)player
216
+ width:(int)width
217
+ height:(int)height {
218
+ self.pipVideoSize = CGSizeMake(width, height);
219
+ if (!CGSizeEqualToSize(CGSizeZero, player.videoAreaFrame.size)) {
220
+ self.pipVideoFrame = player.videoAreaFrame;
221
+ } else {
222
+ self.pipVideoFrame = player.playerView.frame;
223
+ }
224
+ [self setupPipVideoFrameAndSize];
225
+ }
226
+
227
+ - (void)onError:(TVLManager *)player error:(VeLivePlayerError *)error {
228
+ NSLog(@"VeLiveQuickStartDemo: Error %ld, %@", error.code, error.errorMsg);
229
+ }
230
+
231
+ /// MARK: - VeLivePictureInPictureDelegate
232
+ - (void)pictureInPictureIsReady:
233
+ (VeLivePictureInPictureController *)pictureInPicture {
234
+ NSLog(@"PIP: Picture-in-picture is ready");
235
+ }
236
+
237
+ - (void)pictureInPictureWillStart:
238
+ (VeLivePictureInPictureController *)pictureInPicture {
239
+ NSLog(@"PIP: Picture-in-picture will start...");
240
+ }
241
+
242
+ - (void)pictureInPictureDidStart:
243
+ (VeLivePictureInPictureController *)pictureInPicture {
244
+ NSLog(@"PIP: Picture-in-picture did start");
245
+ if (self.listener) {
246
+ [self.listener onStartPictureInPicture];
247
+ }
248
+ }
249
+ - (void)pictureInPicture:(VeLivePictureInPictureController *)pictureInPicture
250
+ failedToStartWithError:(NSError *)error {
251
+ NSLog(@"PIP: Failed to start picture-in-picture: %@", error);
252
+ if (self.listener) {
253
+ [self.listener onError:error.code extraData:error.userInfo];
254
+ }
255
+ }
256
+ - (void)pictureInPictureWillStop:
257
+ (VeLivePictureInPictureController *)pictureInPicture
258
+ isUserStop:(BOOL)isUserStop {
259
+ NSLog(@"PIP: Picture-in-picture will stop");
260
+ }
261
+ - (void)pictureInPictureDidStop:
262
+ (VeLivePictureInPictureController *)pictureInPicture
263
+ isUserStop:(BOOL)isUserStop {
264
+ NSLog(@"PIP: Picture-in-picture stopped");
265
+ if (self.listener) {
266
+ [self.listener onStopPictureInPicture];
267
+ }
268
+ if (!self.pipAutoStart) {
269
+ [self.pipController destroyPictureInPicture];
270
+ self.pipController = nil;
271
+ }
272
+ }
273
+
274
+ @end