Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit b3239b6

Browse files
committed
Merge pull request #1106 from lappp9/ASVideoNode
[ASVideoNode] Performance enhancements
2 parents 7ecc302 + 526b2ab commit b3239b6

3 files changed

Lines changed: 67 additions & 17 deletions

File tree

1.78 KB
Binary file not shown.

AsyncDisplayKit/ASVideoNode.mm

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@ @interface ASVideoNode ()
2424
AVPlayerItem *_currentItem;
2525
AVPlayer *_player;
2626

27+
ASImageNode *_placeholderImageNode;
28+
2729
ASButtonNode *_playButton;
2830
ASDisplayNode *_playerNode;
2931
ASDisplayNode *_spinner;
3032
NSString *_gravity;
33+
dispatch_queue_t _previewQueue;
3134
}
3235

3336
@end
@@ -40,6 +43,8 @@ - (instancetype)init
4043
return nil;
4144
}
4245

46+
_previewQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
47+
4348
#if DEBUG
4449
NSLog(@"*** Warning: ASVideoNode is a new component - the 1.9.6 version may cause performance hiccups.");
4550
#endif
@@ -58,8 +63,6 @@ - (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfac
5863
if (_shouldBePlaying) {
5964
[self pause];
6065
_shouldBePlaying = YES;
61-
} else {
62-
[self pause];
6366
}
6467
[(UIActivityIndicatorView *)_spinner.view stopAnimating];
6568
[_spinner removeFromSupernode];
@@ -106,6 +109,8 @@ - (void)layout
106109
[super layout];
107110

108111
CGRect bounds = self.bounds;
112+
113+
_placeholderImageNode.frame = bounds;
109114
_playerNode.frame = bounds;
110115
_playerNode.layer.frame = bounds;
111116

@@ -121,18 +126,37 @@ - (void)didLoad
121126
{
122127
[super didLoad];
123128
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didPlayToEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
124-
125-
_playerNode = [[ASDisplayNode alloc] initWithLayerBlock:^CALayer *{
126-
AVPlayerLayer *playerLayer = [[AVPlayerLayer alloc] init];
127-
if (!_player) {
128-
_player = [AVPlayer playerWithPlayerItem:[[AVPlayerItem alloc] initWithAsset:_asset]];
129-
}
130-
playerLayer.player = _player;
131-
playerLayer.videoGravity = [self gravity];
132-
return playerLayer;
133-
}];
134-
135-
[self insertSubnode:_playerNode atIndex:0];
129+
130+
if (_shouldBePlaying) {
131+
_playerNode = [[ASDisplayNode alloc] initWithLayerBlock:^CALayer *{
132+
AVPlayerLayer *playerLayer = [[AVPlayerLayer alloc] init];
133+
if (!_player) {
134+
_player = [AVPlayer playerWithPlayerItem:[[AVPlayerItem alloc] initWithAsset:_asset]];
135+
}
136+
playerLayer.player = _player;
137+
playerLayer.videoGravity = [self gravity];
138+
return playerLayer;
139+
}];
140+
141+
[self insertSubnode:_playerNode atIndex:0];
142+
} else {
143+
dispatch_async(_previewQueue, ^{
144+
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:_asset];
145+
[imageGenerator generateCGImagesAsynchronouslyForTimes:@[[NSValue valueWithCMTime:CMTimeMake(0, 1)]] completionHandler:^(CMTime requestedTime, CGImageRef _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error) {
146+
UIImage *theImage = [UIImage imageWithCGImage:image];
147+
148+
_placeholderImageNode = [[ASImageNode alloc] init];
149+
_placeholderImageNode.layerBacked = YES;
150+
_placeholderImageNode.image = theImage;
151+
_placeholderImageNode.contentMode = UIViewContentModeScaleAspectFit;
152+
153+
dispatch_async(dispatch_get_main_queue(), ^{
154+
_placeholderImageNode.frame = self.bounds;
155+
[self insertSubnode:_placeholderImageNode atIndex:0];
156+
});
157+
}];
158+
});
159+
}
136160
}
137161

138162
- (void)tapped
@@ -286,6 +310,20 @@ - (void)play
286310
}];
287311
}
288312

313+
if (!_playerNode) {
314+
_playerNode = [[ASDisplayNode alloc] initWithLayerBlock:^CALayer *{
315+
AVPlayerLayer *playerLayer = [[AVPlayerLayer alloc] init];
316+
if (!_player) {
317+
_player = [AVPlayer playerWithPlayerItem:[[AVPlayerItem alloc] initWithAsset:_asset]];
318+
}
319+
playerLayer.player = _player;
320+
playerLayer.videoGravity = [self gravity];
321+
return playerLayer;
322+
}];
323+
324+
[self addSubnode:_playerNode];
325+
}
326+
289327
[_player play];
290328
_shouldBePlaying = YES;
291329
_playButton.alpha = 0.0;
@@ -364,4 +402,3 @@ - (void)dealloc
364402
}
365403

366404
@end
367-

AsyncDisplayKitTests/ASVideoNodeTests.m

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,28 @@ - (void)testPlayerIsCreatedInFetchData
127127
XCTAssertNotNil(_videoNode.player);
128128
}
129129

130-
- (void)testPlayerLayerNodeIsAddedOnDidLoad
130+
- (void)testPlayerLayerNodeIsAddedOnDidLoadIfVisibleAndAutoPlaying
131131
{
132132
_videoNode.asset = _firstAsset;
133133

134+
[_videoNode setInterfaceState:ASInterfaceStateNone];
134135
[_videoNode didLoad];
135136

136-
XCTAssert([_videoNode.subnodes containsObject:_videoNode.playerNode]);
137+
XCTAssert(![_videoNode.subnodes containsObject:_videoNode.playerNode]);
137138
}
138139

140+
- (void)testPlayerLayerNodeIsNotAddedIfVisibleButShouldNotBePlaying
141+
{
142+
_videoNode.asset = _firstAsset;
143+
144+
[_videoNode pause];
145+
[_videoNode setInterfaceState:ASInterfaceStateVisible];
146+
[_videoNode didLoad];
147+
148+
XCTAssert(![_videoNode.subnodes containsObject:_videoNode.playerNode]);
149+
}
150+
151+
139152
- (void)testVideoStartsPlayingOnDidDidBecomeVisibleWhenShouldAutoplay
140153
{
141154
_videoNode.asset = _firstAsset;

0 commit comments

Comments
 (0)