PR fixes for iOS sideloaded captions
This commit is contained in:
parent
fa63a9ef87
commit
c9b752454a
170
ios/RCTVideo.m
170
ios/RCTVideo.m
@ -20,6 +20,7 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
BOOL _playerItemObserversSet;
|
BOOL _playerItemObserversSet;
|
||||||
BOOL _playerBufferEmpty;
|
BOOL _playerBufferEmpty;
|
||||||
AVPlayerLayer *_playerLayer;
|
AVPlayerLayer *_playerLayer;
|
||||||
|
BOOL _playerLayerObserverSet;
|
||||||
AVPlayerViewController *_playerViewController;
|
AVPlayerViewController *_playerViewController;
|
||||||
NSURL *_videoURL;
|
NSURL *_videoURL;
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
BOOL _allowsExternalPlayback;
|
BOOL _allowsExternalPlayback;
|
||||||
NSArray * _textTracks;
|
NSArray * _textTracks;
|
||||||
NSDictionary * _selectedTextTrack;
|
NSDictionary * _selectedTextTrack;
|
||||||
|
NSDictionary * _selectedText;
|
||||||
BOOL _playbackStalled;
|
BOOL _playbackStalled;
|
||||||
BOOL _playInBackground;
|
BOOL _playInBackground;
|
||||||
BOOL _playWhenInactive;
|
BOOL _playWhenInactive;
|
||||||
@ -350,7 +352,7 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
bool isNetwork = [RCTConvert BOOL:[source objectForKey:@"isNetwork"]];
|
bool isNetwork = [RCTConvert BOOL:[source objectForKey:@"isNetwork"]];
|
||||||
bool isAsset = [RCTConvert BOOL:[source objectForKey:@"isAsset"]];
|
bool isAsset = [RCTConvert BOOL:[source objectForKey:@"isAsset"]];
|
||||||
NSString *uri = [source objectForKey:@"uri"];
|
NSString *uri = [source objectForKey:@"uri"];
|
||||||
NSString *subtitleUri = self.selectedTextTrack[@"uri"];
|
NSString *subtitleUri = _selectedText[@"uri"];
|
||||||
NSString *type = [source objectForKey:@"type"];
|
NSString *type = [source objectForKey:@"type"];
|
||||||
NSDictionary *headers = [source objectForKey:@"requestHeaders"];
|
NSDictionary *headers = [source objectForKey:@"requestHeaders"];
|
||||||
|
|
||||||
@ -376,19 +378,19 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
asset = [AVURLAsset URLAssetWithURL:[self urlFilePath:uri] options:nil];
|
asset = [AVURLAsset URLAssetWithURL:[self urlFilePath:uri] options:nil];
|
||||||
subAsset = [AVURLAsset URLAssetWithURL:[self urlFilePath:subtitleUri] options:nil];
|
subAsset = [AVURLAsset URLAssetWithURL:[self urlFilePath:subtitleUri] options:nil];
|
||||||
}
|
}
|
||||||
else if (!isNetwork && !isAsset) // this is a relative file hardcoded in the app?
|
else // file passed in through JS, or an asset in the Xcode project
|
||||||
{
|
{
|
||||||
asset = [AVURLAsset URLAssetWithURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]] options:nil];
|
asset = [AVURLAsset URLAssetWithURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]] options:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_textTracks || !self.selectedTextTrack) return [AVPlayerItem playerItemWithAsset:asset];
|
if (!_textTracks || !_selectedText) return [AVPlayerItem playerItemWithAsset:asset];
|
||||||
|
|
||||||
// otherwise sideload text tracks
|
// otherwise sideload text tracks
|
||||||
AVAssetTrack *videoAsset = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;
|
AVAssetTrack *videoAsset = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;
|
||||||
AVAssetTrack *audioAsset = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;
|
AVAssetTrack *audioAsset = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;
|
||||||
AVAssetTrack *subtitleAsset = [subAsset tracksWithMediaType:AVMediaTypeText].firstObject;
|
AVAssetTrack *textAsset = [subAsset tracksWithMediaType:AVMediaTypeText].firstObject;
|
||||||
|
|
||||||
NSLog(@"assets: %@,%@,%@", videoAsset, audioAsset, subtitleAsset);
|
NSLog(@"assets: %@,%@,%@", videoAsset, audioAsset, textAsset);
|
||||||
|
|
||||||
|
|
||||||
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
|
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
|
||||||
@ -407,7 +409,7 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
error:nil];
|
error:nil];
|
||||||
|
|
||||||
[subtitleCompTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.timeRange.duration)
|
[subtitleCompTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.timeRange.duration)
|
||||||
ofTrack:subtitleAsset
|
ofTrack:textAsset
|
||||||
atTime:kCMTimeZero
|
atTime:kCMTimeZero
|
||||||
error:nil];
|
error:nil];
|
||||||
|
|
||||||
@ -454,7 +456,6 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
NSString *orientation = @"undefined";
|
NSString *orientation = @"undefined";
|
||||||
|
|
||||||
if ([_playerItem.asset tracksWithMediaType:AVMediaTypeVideo].count > 0) {
|
if ([_playerItem.asset tracksWithMediaType:AVMediaTypeVideo].count > 0) {
|
||||||
|
|
||||||
AVAssetTrack *videoTrack = [[_playerItem.asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
|
AVAssetTrack *videoTrack = [[_playerItem.asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
|
||||||
width = [NSNumber numberWithFloat:videoTrack.naturalSize.width];
|
width = [NSNumber numberWithFloat:videoTrack.naturalSize.width];
|
||||||
height = [NSNumber numberWithFloat:videoTrack.naturalSize.height];
|
height = [NSNumber numberWithFloat:videoTrack.naturalSize.height];
|
||||||
@ -463,7 +464,6 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
if ((videoTrack.naturalSize.width == preferredTransform.tx
|
if ((videoTrack.naturalSize.width == preferredTransform.tx
|
||||||
&& videoTrack.naturalSize.height == preferredTransform.ty)
|
&& videoTrack.naturalSize.height == preferredTransform.ty)
|
||||||
|| (preferredTransform.tx == 0 && preferredTransform.ty == 0))
|
|| (preferredTransform.tx == 0 && preferredTransform.ty == 0))
|
||||||
|
|
||||||
{
|
{
|
||||||
orientation = @"landscape";
|
orientation = @"landscape";
|
||||||
} else {
|
} else {
|
||||||
@ -638,23 +638,30 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
|
|
||||||
- (void)setCurrentTime:(float)currentTime
|
- (void)setCurrentTime:(float)currentTime
|
||||||
{
|
{
|
||||||
[self setSeek: currentTime];
|
NSDictionary *info = @{
|
||||||
|
@"time": [NSNumber numberWithFloat:currentTime],
|
||||||
|
@"tolerance": [NSNumber numberWithInt:100]
|
||||||
|
};
|
||||||
|
[self setSeek:info];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setSeek:(float)seekTime
|
- (void)setSeek:(NSDictionary *)info
|
||||||
{
|
{
|
||||||
int timeScale = 10000;
|
NSNumber *seekTime = info[@"time"];
|
||||||
|
NSNumber *seekTolerance = info[@"tolerance"];
|
||||||
|
|
||||||
|
int timeScale = 1000;
|
||||||
|
|
||||||
AVPlayerItem *item = _player.currentItem;
|
AVPlayerItem *item = _player.currentItem;
|
||||||
if (item && item.status == AVPlayerItemStatusReadyToPlay) {
|
if (item && item.status == AVPlayerItemStatusReadyToPlay) {
|
||||||
// TODO check loadedTimeRanges
|
// TODO check loadedTimeRanges
|
||||||
|
|
||||||
CMTime cmSeekTime = CMTimeMakeWithSeconds(seekTime, timeScale);
|
CMTime cmSeekTime = CMTimeMakeWithSeconds([seekTime floatValue], timeScale);
|
||||||
CMTime current = item.currentTime;
|
CMTime current = item.currentTime;
|
||||||
// TODO figure out a good tolerance level
|
// TODO figure out a good tolerance level
|
||||||
CMTime tolerance = CMTimeMake(1000, timeScale);
|
CMTime tolerance = CMTimeMake([seekTolerance floatValue], timeScale);
|
||||||
BOOL wasPaused = _paused;
|
BOOL wasPaused = _paused;
|
||||||
|
|
||||||
if (CMTimeCompare(current, cmSeekTime) != 0) {
|
if (CMTimeCompare(current, cmSeekTime) != 0) {
|
||||||
if (!wasPaused) [_player pause];
|
if (!wasPaused) [_player pause];
|
||||||
[_player seekToTime:cmSeekTime toleranceBefore:tolerance toleranceAfter:tolerance completionHandler:^(BOOL finished) {
|
[_player seekToTime:cmSeekTime toleranceBefore:tolerance toleranceAfter:tolerance completionHandler:^(BOOL finished) {
|
||||||
@ -662,22 +669,22 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
[self addPlayerTimeObserver];
|
[self addPlayerTimeObserver];
|
||||||
}
|
}
|
||||||
if (!wasPaused) {
|
if (!wasPaused) {
|
||||||
[self setPaused:false];
|
[self setPaused:false];
|
||||||
}
|
}
|
||||||
if(self.onVideoSeek) {
|
if(self.onVideoSeek) {
|
||||||
self.onVideoSeek(@{@"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(item.currentTime)],
|
self.onVideoSeek(@{@"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(item.currentTime)],
|
||||||
@"seekTime": [NSNumber numberWithFloat:seekTime],
|
@"seekTime": seekTime,
|
||||||
@"target": self.reactTag});
|
@"target": self.reactTag});
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
_pendingSeek = false;
|
_pendingSeek = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: See if this makes sense and if so, actually implement it
|
// TODO: See if this makes sense and if so, actually implement it
|
||||||
_pendingSeek = true;
|
_pendingSeek = true;
|
||||||
_pendingSeekTime = seekTime;
|
_pendingSeekTime = [seekTime floatValue];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,32 +728,20 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
_repeat = repeat;
|
_repeat = repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary*) selectedTextTrack {
|
|
||||||
if (_textTracks) {
|
|
||||||
[self setSideloadedTextTrack];
|
|
||||||
}
|
|
||||||
else [self setStreamingTextTrack];
|
|
||||||
|
|
||||||
return _selectedTextTrack;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setSelectedTextTrack:(NSDictionary *)selectedTextTrack {
|
- (void)setSelectedTextTrack:(NSDictionary *)selectedTextTrack {
|
||||||
|
_selectedTextTrack = selectedTextTrack;
|
||||||
|
|
||||||
_selectedTextTrack = selectedTextTrack;
|
if (_textTracks) {
|
||||||
|
[self setSideloadedText];
|
||||||
|
}
|
||||||
|
else [self setStreamingText];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setSideloadedTextTrack {
|
- (void) setSideloadedText {
|
||||||
NSString *type = _selectedTextTrack[@"type"];
|
NSString *type = _selectedTextTrack[@"type"];
|
||||||
NSArray* textTracks = [self getTextTrackInfo];
|
NSArray* textTracks = [self getTextTrackInfo];
|
||||||
|
|
||||||
if (textTracks==nil) {
|
_selectedText = nil;
|
||||||
_selectedTextTrack = nil;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSDictionary* selectedCaption = nil;
|
|
||||||
|
|
||||||
if ([type isEqualToString:@"disabled"]) {
|
if ([type isEqualToString:@"disabled"]) {
|
||||||
// Do nothing. We want to ensure option is nil
|
// Do nothing. We want to ensure option is nil
|
||||||
@ -754,20 +749,20 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
NSString *selectedValue = _selectedTextTrack[@"value"];
|
NSString *selectedValue = _selectedTextTrack[@"value"];
|
||||||
|
|
||||||
for (int i = 0; i < textTracks.count; ++i) {
|
for (int i = 0; i < textTracks.count; ++i) {
|
||||||
NSDictionary *currentCaption = [textTracks objectAtIndex:i];
|
NSDictionary *currentTextTrack = [textTracks objectAtIndex:i];
|
||||||
|
|
||||||
if ([selectedValue isEqualToString:currentCaption[@"language"]]) {
|
if ([selectedValue isEqualToString:currentTextTrack[@"language"]]) {
|
||||||
selectedCaption = currentCaption;
|
_selectedText = currentTextTrack;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ([type isEqualToString:@"title"]) {
|
} else if ([type isEqualToString:@"title"]) {
|
||||||
NSString *selectedValue = _selectedTextTrack[@"value"];
|
NSString *selectedValue = _selectedTextTrack[@"value"];
|
||||||
for (int i = 0; i < textTracks.count; ++i) {
|
for (int i = 0; i < textTracks.count; ++i) {
|
||||||
NSDictionary *currentCaption = [textTracks objectAtIndex:i];
|
NSDictionary *currentTextTrack = [textTracks objectAtIndex:i];
|
||||||
|
|
||||||
if ([selectedValue isEqualToString:currentCaption[@"title"]]) {
|
if ([selectedValue isEqualToString:currentTextTrack[@"title"]]) {
|
||||||
selectedCaption = currentCaption;
|
_selectedText = currentTextTrack;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -775,28 +770,37 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
if ([_selectedTextTrack[@"value"] isKindOfClass:[NSNumber class]]) {
|
if ([_selectedTextTrack[@"value"] isKindOfClass:[NSNumber class]]) {
|
||||||
int index = [_selectedTextTrack[@"value"] intValue];
|
int index = [_selectedTextTrack[@"value"] intValue];
|
||||||
if (textTracks.count > index) {
|
if (textTracks.count > index) {
|
||||||
selectedCaption = [textTracks objectAtIndex:index];
|
_selectedText = [textTracks objectAtIndex:index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// user's selected language might not be available, or system defaults have captions enabled
|
// user's selected language might not be available, or system defaults have captions enabled
|
||||||
if (selectedCaption==nil || [type isEqualToString:@"default"]) {
|
if (_selectedText==nil || [type isEqualToString:@"default"]) {
|
||||||
CFArrayRef captioningMediaCharacteristics = MACaptionAppearanceCopyPreferredCaptioningMediaCharacteristics(kMACaptionAppearanceDomainUser);
|
CFArrayRef captioningMediaCharacteristics = MACaptionAppearanceCopyPreferredCaptioningMediaCharacteristics(kMACaptionAppearanceDomainUser);
|
||||||
NSArray *captionSettings = (__bridge NSArray*)captioningMediaCharacteristics;
|
NSArray *captionSettings = (__bridge NSArray*)captioningMediaCharacteristics;
|
||||||
if ([captionSettings containsObject: AVMediaCharacteristicTranscribesSpokenDialogForAccessibility]) {
|
if ([captionSettings containsObject: AVMediaCharacteristicTranscribesSpokenDialogForAccessibility]) {
|
||||||
selectedCaption = textTracks.firstObject;
|
// iterate through the textTracks to find a matching option, or default to the first object.
|
||||||
|
_selectedText = textTracks.firstObject;
|
||||||
|
|
||||||
|
NSString * systemLanguage = [[NSLocale preferredLanguages] firstObject];
|
||||||
|
for (int i = 0; i < textTracks.count; ++i) {
|
||||||
|
NSDictionary *currentTextTrack = [textTracks objectAtIndex:i];
|
||||||
|
|
||||||
|
if ([systemLanguage isEqualToString:currentTextTrack[@"language"]]) {
|
||||||
|
_selectedText = currentTextTrack;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_selectedTextTrack = selectedCaption;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) setStreamingTextTrack {
|
-(void) setStreamingText {
|
||||||
NSString *type = _selectedTextTrack[@"type"];
|
NSString *type = _selectedTextTrack[@"type"];
|
||||||
AVMediaSelectionGroup *group = [_player.currentItem.asset
|
AVMediaSelectionGroup *group = [_player.currentItem.asset
|
||||||
mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicLegible];
|
mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicLegible];
|
||||||
AVMediaSelectionOption *option;
|
AVMediaSelectionOption *mediaOption;
|
||||||
|
|
||||||
if ([type isEqualToString:@"disabled"]) {
|
if ([type isEqualToString:@"disabled"]) {
|
||||||
// Do nothing. We want to ensure option is nil
|
// Do nothing. We want to ensure option is nil
|
||||||
@ -813,7 +817,7 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
objectAtIndex:0];
|
objectAtIndex:0];
|
||||||
}
|
}
|
||||||
if ([value isEqualToString:optionValue]) {
|
if ([value isEqualToString:optionValue]) {
|
||||||
option = currentOption;
|
mediaOption = currentOption;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -823,7 +827,7 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
if ([_selectedTextTrack[@"value"] isKindOfClass:[NSNumber class]]) {
|
if ([_selectedTextTrack[@"value"] isKindOfClass:[NSNumber class]]) {
|
||||||
int index = [_selectedTextTrack[@"value"] intValue];
|
int index = [_selectedTextTrack[@"value"] intValue];
|
||||||
if (group.options.count > index) {
|
if (group.options.count > index) {
|
||||||
option = [group.options objectAtIndex:index];
|
mediaOption = [group.options objectAtIndex:index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // default. invalid type or "system"
|
} else { // default. invalid type or "system"
|
||||||
@ -832,12 +836,15 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If a match isn't found, option will be nil and text tracks will be disabled
|
// If a match isn't found, option will be nil and text tracks will be disabled
|
||||||
[_player.currentItem selectMediaOption:option inMediaSelectionGroup:group];
|
[_player.currentItem selectMediaOption:mediaOption inMediaSelectionGroup:group];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setTextTracks:(NSArray*) textTracks;
|
- (void)setTextTracks:(NSArray*) textTracks;
|
||||||
{
|
{
|
||||||
_textTracks = textTracks;
|
_textTracks = textTracks;
|
||||||
|
|
||||||
|
// in case textTracks was set after selectedTextTrack
|
||||||
|
if (_selectedTextTrack) [self setSelectedTextTrack:_selectedTextTrack];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *)getTextTrackInfo
|
- (NSArray *)getTextTrackInfo
|
||||||
@ -852,13 +859,16 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicLegible];
|
mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicLegible];
|
||||||
for (int i = 0; i < group.options.count; ++i) {
|
for (int i = 0; i < group.options.count; ++i) {
|
||||||
AVMediaSelectionOption *currentOption = [group.options objectAtIndex:i];
|
AVMediaSelectionOption *currentOption = [group.options objectAtIndex:i];
|
||||||
NSString *title = [[[currentOption commonMetadata]
|
NSString *title = @"";
|
||||||
valueForKey:@"value"]
|
NSArray *values = [[currentOption commonMetadata] valueForKey:@"value"];
|
||||||
objectAtIndex:0];
|
if (values.count > 0) {
|
||||||
|
title = [values objectAtIndex:0];
|
||||||
|
}
|
||||||
|
NSString *language = [currentOption extendedLanguageTag] ? [currentOption extendedLanguageTag] : @"";
|
||||||
NSDictionary *textTrack = @{
|
NSDictionary *textTrack = @{
|
||||||
@"index": [NSNumber numberWithInt:i],
|
@"index": [NSNumber numberWithInt:i],
|
||||||
@"title": title,
|
@"title": title,
|
||||||
@"language": [currentOption extendedLanguageTag]
|
@"language": language
|
||||||
};
|
};
|
||||||
[textTracks addObject:textTrack];
|
[textTracks addObject:textTrack];
|
||||||
}
|
}
|
||||||
@ -931,20 +941,21 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
|
|
||||||
- (void)usePlayerLayer
|
- (void)usePlayerLayer
|
||||||
{
|
{
|
||||||
if( _player )
|
if( _player )
|
||||||
{
|
{
|
||||||
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
|
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
|
||||||
_playerLayer.frame = self.bounds;
|
_playerLayer.frame = self.bounds;
|
||||||
_playerLayer.needsDisplayOnBoundsChange = YES;
|
_playerLayer.needsDisplayOnBoundsChange = YES;
|
||||||
|
|
||||||
// to prevent video from being animated when resizeMode is 'cover'
|
// to prevent video from being animated when resizeMode is 'cover'
|
||||||
// resize mode must be set before layer is added
|
// resize mode must be set before layer is added
|
||||||
[self setResizeMode:_resizeMode];
|
[self setResizeMode:_resizeMode];
|
||||||
[_playerLayer addObserver:self forKeyPath:readyForDisplayKeyPath options:NSKeyValueObservingOptionNew context:nil];
|
[_playerLayer addObserver:self forKeyPath:readyForDisplayKeyPath options:NSKeyValueObservingOptionNew context:nil];
|
||||||
|
_playerLayerObserverSet = YES;
|
||||||
[self.layer addSublayer:_playerLayer];
|
|
||||||
self.layer.needsDisplayOnBoundsChange = YES;
|
[self.layer addSublayer:_playerLayer];
|
||||||
}
|
self.layer.needsDisplayOnBoundsChange = YES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setControls:(BOOL)controls
|
- (void)setControls:(BOOL)controls
|
||||||
@ -978,9 +989,12 @@ static NSString *const timedMetadata = @"timedMetadata";
|
|||||||
|
|
||||||
- (void)removePlayerLayer
|
- (void)removePlayerLayer
|
||||||
{
|
{
|
||||||
[_playerLayer removeFromSuperlayer];
|
[_playerLayer removeFromSuperlayer];
|
||||||
|
if (_playerLayerObserverSet) {
|
||||||
[_playerLayer removeObserver:self forKeyPath:readyForDisplayKeyPath];
|
[_playerLayer removeObserver:self forKeyPath:readyForDisplayKeyPath];
|
||||||
_playerLayer = nil;
|
_playerLayerObserverSet = NO;
|
||||||
|
}
|
||||||
|
_playerLayer = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - RCTVideoPlayerViewControllerDelegate
|
#pragma mark - RCTVideoPlayerViewControllerDelegate
|
||||||
|
Loading…
Reference in New Issue
Block a user