mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 22:55:00 +00:00
Updating and adding a few APIs for ASVideoNode
This commit is contained in:
@@ -14,9 +14,9 @@
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ASVideoNodePlayerStateUnknown,
|
ASVideoNodePlayerStateUnknown,
|
||||||
ASVideoNodePlayerStatePlaying,
|
ASVideoNodePlayerStateInitialLoading,
|
||||||
ASVideoNodePlayerStateStartupLoading,
|
|
||||||
ASVideoNodePlayerStateLoading,
|
ASVideoNodePlayerStateLoading,
|
||||||
|
ASVideoNodePlayerStatePlaying,
|
||||||
ASVideoNodePlayerStatePaused,
|
ASVideoNodePlayerStatePaused,
|
||||||
ASVideoNodePlayerStateFinished
|
ASVideoNodePlayerStateFinished
|
||||||
} ASVideoNodePlayerState;
|
} ASVideoNodePlayerState;
|
||||||
@@ -48,6 +48,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@property (nonatomic, assign, readwrite) BOOL shouldAutorepeat;
|
@property (nonatomic, assign, readwrite) BOOL shouldAutorepeat;
|
||||||
|
|
||||||
@property (nonatomic, assign, readwrite) BOOL muted;
|
@property (nonatomic, assign, readwrite) BOOL muted;
|
||||||
|
@property (nonatomic, assign, readwrite) BOOL shouldAggressivelyRecoverFromStall;
|
||||||
|
|
||||||
@property (nonatomic, assign, readonly) ASVideoNodePlayerState playerState;
|
@property (nonatomic, assign, readonly) ASVideoNodePlayerState playerState;
|
||||||
//! Defaults to 100
|
//! Defaults to 100
|
||||||
@@ -69,26 +70,26 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
* @abstract Delegate method invoked when the node's video has played to its end time.
|
* @abstract Delegate method invoked when the node's video has played to its end time.
|
||||||
* @param videoNode The video node has played to its end time.
|
* @param videoNode The video node has played to its end time.
|
||||||
*/
|
*/
|
||||||
- (void)videoPlaybackDidFinish:(ASVideoNode *)videoNode;
|
- (void)videoDidPlayToEnd:(ASVideoNode *)videoNode;
|
||||||
/**
|
/**
|
||||||
* @abstract Delegate method invoked the node is tapped.
|
* @abstract Delegate method invoked the node is tapped.
|
||||||
* @param videoNode The video node that was tapped.
|
* @param videoNode The video node that was tapped.
|
||||||
* @discussion The video's play state is toggled if this method is not implemented.
|
* @discussion The video's play state is toggled if this method is not implemented.
|
||||||
*/
|
*/
|
||||||
- (void)videoNodeWasTapped:(ASVideoNode *)videoNode;
|
- (void)didTapVideoNode:(ASVideoNode *)videoNode;
|
||||||
/**
|
/**
|
||||||
* @abstract Delegate method invoked when player changes state.
|
* @abstract Delegate method invoked when player changes state.
|
||||||
* @param videoNode The video node that was tapped.
|
* @param videoNode The video node.
|
||||||
* @param state player state before this change.
|
* @param state player state before this change.
|
||||||
* @param toSate player new state.
|
* @param toState player new state.
|
||||||
* @discussion This method is called after each state change
|
* @discussion This method is called after each state change
|
||||||
*/
|
*/
|
||||||
- (void)videoNode:(ASVideoNode *)videoNode willChangePlayerState:(ASVideoNodePlayerState)state toState:(ASVideoNodePlayerState)toSate;
|
- (void)videoNode:(ASVideoNode *)videoNode willChangePlayerState:(ASVideoNodePlayerState)state toState:(ASVideoNodePlayerState)toState;
|
||||||
/**
|
/**
|
||||||
* @abstract Ssks delegate if state change is allowed
|
* @abstract Ssks delegate if state change is allowed
|
||||||
* ASVideoNodePlayerStatePlaying or ASVideoNodePlayerStatePaused.
|
* ASVideoNodePlayerStatePlaying or ASVideoNodePlayerStatePaused.
|
||||||
* asks delegate if state change is allowed.
|
* asks delegate if state change is allowed.
|
||||||
* @param videoNode The video node that was tapped.
|
* @param videoNode The video node.
|
||||||
* @param state player state that is going to be set.
|
* @param state player state that is going to be set.
|
||||||
* @discussion Delegate method invoked when player changes it's state to
|
* @discussion Delegate method invoked when player changes it's state to
|
||||||
* ASVideoNodePlayerStatePlaying or ASVideoNodePlayerStatePaused
|
* ASVideoNodePlayerStatePlaying or ASVideoNodePlayerStatePaused
|
||||||
@@ -97,10 +98,32 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
- (BOOL)videoNode:(ASVideoNode*)videoNode shouldChangePlayerStateTo:(ASVideoNodePlayerState)state;
|
- (BOOL)videoNode:(ASVideoNode*)videoNode shouldChangePlayerStateTo:(ASVideoNodePlayerState)state;
|
||||||
/**
|
/**
|
||||||
* @abstract Delegate method invoked when player playback time is updated.
|
* @abstract Delegate method invoked when player playback time is updated.
|
||||||
* @param videoNode The video node that was tapped.
|
* @param videoNode The video node.
|
||||||
* @param second current playback time in seconds.
|
* @param second current playback time in seconds.
|
||||||
*/
|
*/
|
||||||
- (void)videoNode:(ASVideoNode *)videoNode didPlayToSecond:(NSTimeInterval)second;
|
- (void)videoNode:(ASVideoNode *)videoNode didPlayToTimeInterval:(NSTimeInterval)timeInterval;
|
||||||
|
/**
|
||||||
|
* @abstract Delegate method invoked when the video player stalls.
|
||||||
|
* @param videoNode The video node that has experienced the stall
|
||||||
|
* @param second Current playback time when the stall happens
|
||||||
|
*/
|
||||||
|
- (void)videoNode:(ASVideoNode *)videoNode didStallAtTimeInterval:(NSTimeInterval)timeInterval;
|
||||||
|
/**
|
||||||
|
* @abstract Delegate method invoked when the video player starts the inital asset loading
|
||||||
|
* @param videoNode The videoNode
|
||||||
|
*/
|
||||||
|
- (void)videoNodeDidStartInitialLoading:(ASVideoNode *)videoNode;
|
||||||
|
/**
|
||||||
|
* @abstract Delegate method invoked when the video is done loading the asset and can start the playback
|
||||||
|
* @param videoNode The videoNode
|
||||||
|
*/
|
||||||
|
- (void)videoNodeDidFinishInitialLoading:(ASVideoNode *)videoNode;
|
||||||
|
/**
|
||||||
|
* @abstract Delegate method invoked when the video node has recovered from the stall
|
||||||
|
* @param videoNode The videoNode
|
||||||
|
*/
|
||||||
|
- (void)videoNodeDidRecoverFromStall:(ASVideoNode *)videoNode;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
#endif
|
#endif
|
||||||
@@ -38,17 +38,21 @@ static NSString * const kStatus = @"status";
|
|||||||
__weak id<ASVideoNodeDelegate> _delegate;
|
__weak id<ASVideoNodeDelegate> _delegate;
|
||||||
struct {
|
struct {
|
||||||
unsigned int delegateVideNodeShouldChangePlayerStateTo:1;
|
unsigned int delegateVideNodeShouldChangePlayerStateTo:1;
|
||||||
unsigned int delegateVideoPlaybackDidFinish:1;
|
unsigned int delegateVideoDidPlayToEnd:1;
|
||||||
unsigned int delegateVideoNodeWasTapped:1;
|
unsigned int delegateDidTapVideoNode:1;
|
||||||
unsigned int delegateVideoNodeWillChangePlayerStateToState:1;
|
unsigned int delegateVideoNodeWillChangePlayerStateToState:1;
|
||||||
unsigned int delegateVideoNodeDidPlayToSecond:1;
|
unsigned int delegateVideoNodeDidPlayToTimeInterval:1;
|
||||||
|
unsigned int delegateVideoNodeDidStartInitialLoading:1;
|
||||||
|
unsigned int delegateVideoNodeDidFinishInitialLoading:1;
|
||||||
|
unsigned int delegateVideoNodeDidStallAtTimeInterval:1;
|
||||||
|
unsigned int delegateVideoNodeDidRecoverFromStall:1;
|
||||||
} _delegateFlags;
|
} _delegateFlags;
|
||||||
|
|
||||||
BOOL _shouldBePlaying;
|
BOOL _shouldBePlaying;
|
||||||
|
|
||||||
BOOL _shouldAutorepeat;
|
BOOL _shouldAutorepeat;
|
||||||
BOOL _shouldAutoplay;
|
BOOL _shouldAutoplay;
|
||||||
|
BOOL _shouldAggressivelyRecoverFromStall;
|
||||||
BOOL _muted;
|
BOOL _muted;
|
||||||
|
|
||||||
ASVideoNodePlayerState _playerState;
|
ASVideoNodePlayerState _playerState;
|
||||||
@@ -164,6 +168,7 @@ static NSString * const kStatus = @"status";
|
|||||||
|
|
||||||
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||||
[notificationCenter addObserver:self selector:@selector(didPlayToEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
|
[notificationCenter addObserver:self selector:@selector(didPlayToEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(videoNodeDidStall:) name:AVPlayerItemPlaybackStalledNotification object:playerItem];
|
||||||
[notificationCenter addObserver:self selector:@selector(errorWhilePlaying:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem];
|
[notificationCenter addObserver:self selector:@selector(errorWhilePlaying:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem];
|
||||||
[notificationCenter addObserver:self selector:@selector(errorWhilePlaying:) name:AVPlayerItemNewErrorLogEntryNotification object:playerItem];
|
[notificationCenter addObserver:self selector:@selector(errorWhilePlaying:) name:AVPlayerItemNewErrorLogEntryNotification object:playerItem];
|
||||||
}
|
}
|
||||||
@@ -181,6 +186,7 @@ static NSString * const kStatus = @"status";
|
|||||||
|
|
||||||
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||||
[notificationCenter removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
|
[notificationCenter removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
|
||||||
|
[notificationCenter removeObserver:self name: AVPlayerItemPlaybackStalledNotification object:playerItem];
|
||||||
[notificationCenter removeObserver:self name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem];
|
[notificationCenter removeObserver:self name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem];
|
||||||
[notificationCenter removeObserver:self name:AVPlayerItemNewErrorLogEntryNotification object:playerItem];
|
[notificationCenter removeObserver:self name:AVPlayerItemNewErrorLogEntryNotification object:playerItem];
|
||||||
}
|
}
|
||||||
@@ -313,12 +319,12 @@ static NSString * const kStatus = @"status";
|
|||||||
if (_placeholderImageNode.image == nil) {
|
if (_placeholderImageNode.image == nil) {
|
||||||
[self generatePlaceholderImage];
|
[self generatePlaceholderImage];
|
||||||
}
|
}
|
||||||
if (_shouldBePlaying) {
|
|
||||||
self.playerState = ASVideoNodePlayerStatePlaying;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if ([keyPath isEqualToString:kPlaybackLikelyToKeepUpKey]) {
|
} else if ([keyPath isEqualToString:kPlaybackLikelyToKeepUpKey]) {
|
||||||
if (_shouldBePlaying && [change[NSKeyValueChangeNewKey] boolValue] == true && ASInterfaceStateIncludesVisible(self.interfaceState)) {
|
if (_shouldBePlaying && (_shouldAggressivelyRecoverFromStall || [change[NSKeyValueChangeNewKey] boolValue]) && ASInterfaceStateIncludesVisible(self.interfaceState)) {
|
||||||
|
if (self.playerState == ASVideoNodePlayerStateLoading && _delegateFlags.delegateVideoNodeDidRecoverFromStall) {
|
||||||
|
[_delegate videoNodeDidRecoverFromStall:self];
|
||||||
|
}
|
||||||
[self play]; // autoresume after buffer catches up
|
[self play]; // autoresume after buffer catches up
|
||||||
}
|
}
|
||||||
} else if ([keyPath isEqualToString:kplaybackBufferEmpty]) {
|
} else if ([keyPath isEqualToString:kplaybackBufferEmpty]) {
|
||||||
@@ -331,8 +337,8 @@ static NSString * const kStatus = @"status";
|
|||||||
|
|
||||||
- (void)tapped
|
- (void)tapped
|
||||||
{
|
{
|
||||||
if (_delegateFlags.delegateVideoNodeWasTapped) {
|
if (_delegateFlags.delegateDidTapVideoNode) {
|
||||||
[_delegate videoNodeWasTapped:self];
|
[_delegate didTapVideoNode:self];
|
||||||
} else {
|
} else {
|
||||||
if (_shouldBePlaying) {
|
if (_shouldBePlaying) {
|
||||||
[self pause];
|
[self pause];
|
||||||
@@ -349,10 +355,20 @@ static NSString * const kStatus = @"status";
|
|||||||
{
|
{
|
||||||
ASDN::MutexLocker l(_videoLock);
|
ASDN::MutexLocker l(_videoLock);
|
||||||
AVAsset *asset = self.asset;
|
AVAsset *asset = self.asset;
|
||||||
|
// Return immediately if the asset is nil;
|
||||||
|
if (asset == nil || self.playerState == ASVideoNodePlayerStateInitialLoading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
NSArray<NSString *> *requestedKeys = @[@"playable"];
|
NSArray<NSString *> *requestedKeys = @[@"playable"];
|
||||||
self.playerState = ASVideoNodePlayerStateStartupLoading;
|
self.playerState = ASVideoNodePlayerStateInitialLoading;
|
||||||
|
if (_delegateFlags.delegateVideoNodeDidStartInitialLoading) {
|
||||||
|
[_delegate videoNodeDidStartInitialLoading:self];
|
||||||
|
}
|
||||||
[asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:^{
|
[asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:^{
|
||||||
ASPerformBlockOnMainThread(^{
|
ASPerformBlockOnMainThread(^{
|
||||||
|
if (_delegateFlags.delegateVideoNodeDidFinishInitialLoading) {
|
||||||
|
[_delegate videoNodeDidFinishInitialLoading:self];
|
||||||
|
}
|
||||||
[self prepareToPlayAsset:asset withKeys:requestedKeys];
|
[self prepareToPlayAsset:asset withKeys:requestedKeys];
|
||||||
});
|
});
|
||||||
}];
|
}];
|
||||||
@@ -366,8 +382,8 @@ static NSString * const kStatus = @"status";
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_delegateFlags.delegateVideoNodeDidPlayToSecond) {
|
if (_delegateFlags.delegateVideoNodeDidPlayToTimeInterval) {
|
||||||
[_delegate videoNode:self didPlayToSecond:timeInSeconds];
|
[_delegate videoNode:self didPlayToTimeInterval:timeInSeconds];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,10 +498,14 @@ static NSString * const kStatus = @"status";
|
|||||||
memset(&_delegateFlags, 0, sizeof(_delegateFlags));
|
memset(&_delegateFlags, 0, sizeof(_delegateFlags));
|
||||||
} else {
|
} else {
|
||||||
_delegateFlags.delegateVideNodeShouldChangePlayerStateTo = [_delegate respondsToSelector:@selector(videoNode:shouldChangePlayerStateTo:)];
|
_delegateFlags.delegateVideNodeShouldChangePlayerStateTo = [_delegate respondsToSelector:@selector(videoNode:shouldChangePlayerStateTo:)];
|
||||||
_delegateFlags.delegateVideoPlaybackDidFinish = [_delegate respondsToSelector:@selector(videoPlaybackDidFinish:)];
|
_delegateFlags.delegateVideoDidPlayToEnd = [_delegate respondsToSelector:@selector(videoDidPlayToEnd:)];
|
||||||
_delegateFlags.delegateVideoNodeWasTapped = [_delegate respondsToSelector:@selector(videoNodeWasTapped:)];
|
_delegateFlags.delegateDidTapVideoNode = [_delegate respondsToSelector:@selector(didTapVideoNode:)];
|
||||||
_delegateFlags.delegateVideoNodeWillChangePlayerStateToState = [_delegate respondsToSelector:@selector(videoNode:willChangePlayerState:toState:)];
|
_delegateFlags.delegateVideoNodeWillChangePlayerStateToState = [_delegate respondsToSelector:@selector(videoNode:willChangePlayerState:toState:)];
|
||||||
_delegateFlags.delegateVideoNodeDidPlayToSecond = [_delegate respondsToSelector:@selector(videoNode:didPlayToSecond:)];
|
_delegateFlags.delegateVideoNodeDidPlayToTimeInterval = [_delegate respondsToSelector:@selector(videoNode:didPlayToTimeInterval:)];
|
||||||
|
_delegateFlags.delegateVideoNodeDidStartInitialLoading = [_delegate respondsToSelector:@selector(videoNodeDidStartInitialLoading:)];
|
||||||
|
_delegateFlags.delegateVideoNodeDidFinishInitialLoading = [_delegate respondsToSelector:@selector(videoNodeDidFinishInitialLoading:)];
|
||||||
|
_delegateFlags.delegateVideoNodeDidStallAtTimeInterval = [_delegate respondsToSelector:@selector(videoNode:didStallAtTimeInterval:)];
|
||||||
|
_delegateFlags.delegateVideoNodeDidRecoverFromStall = [_delegate respondsToSelector:@selector(videoNodeDidRecoverFromStall:)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,8 +652,8 @@ static NSString * const kStatus = @"status";
|
|||||||
- (void)didPlayToEnd:(NSNotification *)notification
|
- (void)didPlayToEnd:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
self.playerState = ASVideoNodePlayerStateFinished;
|
self.playerState = ASVideoNodePlayerStateFinished;
|
||||||
if (_delegateFlags.delegateVideoPlaybackDidFinish) {
|
if (_delegateFlags.delegateVideoDidPlayToEnd) {
|
||||||
[_delegate videoPlaybackDidFinish:self];
|
[_delegate videoDidPlayToEnd:self];
|
||||||
}
|
}
|
||||||
[_player seekToTime:kCMTimeZero];
|
[_player seekToTime:kCMTimeZero];
|
||||||
|
|
||||||
@@ -644,6 +664,15 @@ static NSString * const kStatus = @"status";
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)videoNodeDidStall:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
self.playerState = ASVideoNodePlayerStateLoading;
|
||||||
|
[self showSpinner];
|
||||||
|
if (_delegateFlags.delegateVideoNodeDidStallAtTimeInterval) {
|
||||||
|
[_delegate videoNode:self didStallAtTimeInterval:CMTimeGetSeconds(_player.currentItem.currentTime)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)errorWhilePlaying:(NSNotification *)notification
|
- (void)errorWhilePlaying:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
if ([notification.name isEqualToString:AVPlayerItemFailedToPlayToEndTimeNotification]) {
|
if ([notification.name isEqualToString:AVPlayerItemFailedToPlayToEndTimeNotification]) {
|
||||||
|
|||||||
Reference in New Issue
Block a user