From 285e9ca8817ff7de4f6ac2d4cf51f944ef5237c9 Mon Sep 17 00:00:00 2001 From: virgil Date: Fri, 15 Apr 2022 17:29:56 +0800 Subject: [PATCH 01/35] =?UTF-8?q?fix:=20=F0=9F=90=9B=20support=20ios=20cam?= =?UTF-8?q?eraroll?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Video.js | 2 +- ios/Video/RCTVideo.m | 64 ++++++++++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/Video.js b/Video.js index b492d48b..6af4fc3a 100644 --- a/Video.js +++ b/Video.js @@ -275,7 +275,7 @@ export default class Video extends Component { } const isNetwork = !!(uri && uri.match(/^https?:/)); - const isAsset = !!(uri && uri.match(/^(assets-library|ipod-library|file|content|ms-appx|ms-appdata):/)); + const isAsset = !!(uri && uri.match(/^(assets-library|ph|ipod-library|file|content|ms-appx|ms-appdata):/)); let nativeResizeMode; const RCTVideoInstance = this.getViewManagerConfig('RCTVideo'); diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index a757c08a..f2255007 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -5,6 +5,7 @@ #import #include #include +#import static NSString *const statusKeyPath = @"status"; static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"; @@ -492,22 +493,22 @@ static int const RCTVideoUnset = -1; handler([AVPlayerItem playerItemWithAsset:mixComposition]); } -- (void)playerItemForSource:(NSDictionary *)source withCallback:(void(^)(AVPlayerItem *))handler -{ +- (void)loadAssetFromSource:(NSDictionary *)source withCallback:(void(^)(AVURLAsset *asset, NSMutableDictionary *assetOptions)) handler { bool isNetwork = [RCTConvert BOOL:[source objectForKey:@"isNetwork"]]; bool isAsset = [RCTConvert BOOL:[source objectForKey:@"isAsset"]]; bool shouldCache = [RCTConvert BOOL:[source objectForKey:@"shouldCache"]]; + NSString *uri = [source objectForKey:@"uri"]; NSString *type = [source objectForKey:@"type"]; - AVURLAsset *asset; + if (!uri || [uri isEqualToString:@""]) { DebugLog(@"Could not find video URL in source '%@'", source); return; } NSURL *url = isNetwork || isAsset - ? [NSURL URLWithString:uri] - : [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]]; + ? [NSURL URLWithString:uri] + : [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]]; NSMutableDictionary *assetOptions = [[NSMutableDictionary alloc] init]; if (isNetwork) { @@ -529,26 +530,43 @@ static int const RCTVideoUnset = -1; return; } #endif - - asset = [AVURLAsset URLAssetWithURL:url options:assetOptions]; + handler([AVURLAsset URLAssetWithURL:url options:assetOptions], assetOptions); } else if (isAsset) { - asset = [AVURLAsset URLAssetWithURL:url options:nil]; + if ([uri hasPrefix:@"ph://"]) { + NSString *assetId = [uri substringFromIndex:@"ph://".length]; + PHAsset *asset = [[PHAsset fetchAssetsWithLocalIdentifiers:@[assetId] options:nil] firstObject]; + PHVideoRequestOptions *options = [PHVideoRequestOptions new]; + options.networkAccessAllowed = YES; + + [[PHCachingImageManager new] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) { + handler((AVURLAsset *)asset, assetOptions); + }]; + } else { + handler([AVURLAsset URLAssetWithURL:url options:nil], assetOptions); + } } else { - asset = [AVURLAsset URLAssetWithURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]] options:nil]; + AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]] options:nil]; + handler(asset, assetOptions); } - // Reset _loadingRequest - if (_loadingRequest != nil) { - [_loadingRequest finishLoading]; - } - _requestingCertificate = NO; - _requestingCertificateErrored = NO; - // End Reset _loadingRequest - if (self->_drm != nil) { - dispatch_queue_t queue = dispatch_queue_create("assetQueue", nil); - [asset.resourceLoader setDelegate:self queue:queue]; - } - - [self playerItemPrepareText:asset assetOptions:assetOptions withCallback:handler]; +} + +- (void)playerItemForSource:(NSDictionary *)source withCallback:(void(^)(AVPlayerItem *))handler +{ + [self loadAssetFromSource:source withCallback:^(AVURLAsset *asset, NSMutableDictionary *assetOptions) { + // Reset _loadingRequest + if (self->_loadingRequest != nil) { + [self->_loadingRequest finishLoading]; + } + self->_requestingCertificate = NO; + self->_requestingCertificateErrored = NO; + // End Reset _loadingRequest + if (self->_drm != nil) { + dispatch_queue_t queue = dispatch_queue_create("assetQueue", nil); + [asset.resourceLoader setDelegate:self queue:queue]; + } + + [self playerItemPrepareText:asset assetOptions:assetOptions withCallback:handler]; + }]; } #if __has_include() @@ -2028,4 +2046,4 @@ didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest { } #endif -@end +@end \ No newline at end of file From 329df1d91abda9fd882c1ff2c1b7aa69a67bdb54 Mon Sep 17 00:00:00 2001 From: virgil Date: Fri, 15 Apr 2022 17:36:23 +0800 Subject: [PATCH 02/35] =?UTF-8?q?chore:=20=F0=9F=A4=96=20update=20changelo?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc7f5943..6dcc12f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - Add Google's maven repository to avoid build error [#2552] (https://github.com/react-native-video/react-native-video/pull/2552) +- Fix crash when the source is a cameraroll [#2639] (https://github.com/react-native-video/react-native-video/pull/2639) + ### Version 5.2.0 - Fix for tvOS native audio menu language selector From 3a4cb7f6d939a85d2c6118c821f3dc8970dee115 Mon Sep 17 00:00:00 2001 From: olivier bouillet Date: Thu, 23 Jun 2022 22:54:03 +0200 Subject: [PATCH 03/35] feat(android): add new apis to query device capabilities getWidevineLevel => integer between 0 and 3 isCodecSupported(codec, width, height) => boolean isHEVCSupported() => boolean --- API.md | 66 +++++++++++ Video.js | 3 +- .../brentvatne/react/ReactVideoPackage.java | 4 +- .../react/VideoDecoderPropertiesModule.java | 105 ++++++++++++++++++ 4 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.java diff --git a/API.md b/API.md index 9ac52616..b735a026 100644 --- a/API.md +++ b/API.md @@ -344,6 +344,13 @@ var styles = StyleSheet.create({ |[restoreUserInterfaceForPictureInPictureStop](#restoreuserinterfaceforpictureinpicturestop)|iOS| |[seek](#seek)|All| +### Static methods + +| Name |Plateforms Support | +|--|--| +|[getWidevineLevel](#getWidevineLevel)|Android| +|[isCodecSupported](#isCodecSupported)|Android| +|[isHEVCSupported](#isHEVCSupported)|Android| ### Configurable props @@ -1333,8 +1340,67 @@ this.player.seek(120, 50); // Seek to 2 minutes with +/- 50 milliseconds accurac Platforms: iOS +#### Static methods +### Video Decoding capabilities +A module embed in ReactNativeVideo allow to query device supported feature. +To use it include the module as following: +```javascript +import { VideoDecoderProperties } from '@ifs/react-native-video-enhanced' +``` + +Platforms: Android + +#### getWidevineLevel + +Indicates whether the widevine level supported by device. + +Possible results: +- **0** - unable to determine widevine support (typically not supported) +- **1**, **2**, **3** - Widevine level supported + +Platforms: Android + +Example: + +``` +VideoDecoderProperties.getWidevineLevel().then((widevineLevel) => { + ... +} +``` + +#### isCodecSupported + +Indicates whether the provided codec is supported level supported by device. + +parameters: +- **mimetype**: mime type of codec to query +- **width**, **height**: resolution to query + +Possible results: +- **true** - codec supported +- **false** - codec is not supported + +Example: +``` +VideoDecoderProperties.isCodecSupported('video/avc', 1920, 1080).then( + ... +} +``` +Platforms: Android + +#### isHEVCSupported + +Helper which Indicates whether the provided HEVC/1920*1080 is supported level supported by device. +It uses isCodecSupported internally. + +Example: +``` +VideoDecoderProperties.isHEVCSupported().then((hevcSupported) => { + ... +} +``` ### iOS App Transport Security diff --git a/Video.js b/Video.js index dad262b9..7fd563bb 100644 --- a/Video.js +++ b/Video.js @@ -14,7 +14,8 @@ const styles = StyleSheet.create({ }, }); -export { TextTrackType, FilterType, DRMType }; +const { VideoDecoderProperties } = NativeModules +export { TextTrackType, FilterType, DRMType, VideoDecoderProperties } export default class Video extends Component { diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoPackage.java b/android/src/main/java/com/brentvatne/react/ReactVideoPackage.java index f7a5d02a..23bedad6 100644 --- a/android/src/main/java/com/brentvatne/react/ReactVideoPackage.java +++ b/android/src/main/java/com/brentvatne/react/ReactVideoPackage.java @@ -25,7 +25,9 @@ public class ReactVideoPackage implements ReactPackage { @Override public List createNativeModules(ReactApplicationContext reactContext) { - return Collections.emptyList(); + return Collections.singletonList( + new VideoDecoderPropertiesModule(reactContext) + ); } // Deprecated RN 0.47 diff --git a/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.java b/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.java new file mode 100644 index 00000000..12ae388c --- /dev/null +++ b/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.java @@ -0,0 +1,105 @@ +package com.brentvatne.react; + +import android.annotation.SuppressLint; +import android.media.MediaCodecList; +import android.media.MediaDrm; +import android.media.MediaFormat; +import android.media.UnsupportedSchemeException; +import android.os.Build; + +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; + +import java.util.UUID; + +@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) +public class VideoDecoderPropertiesModule extends ReactContextBaseJavaModule { + + ReactApplicationContext reactContext; + + @NonNull + @Override + public String getName() { + return "VideoDecoderProperties"; + } + + @SuppressLint("ObsoleteSdkInt") + @ReactMethod + public void getWidevineLevel(Promise p) { + int widevineLevel = 0; + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) { + final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL); + final String WIDEVINE_SECURITY_LEVEL_1 = "L1"; + final String WIDEVINE_SECURITY_LEVEL_2 = "L2"; + final String WIDEVINE_SECURITY_LEVEL_3 = "L3"; + final String SECURITY_LEVEL_PROPERTY = "securityLevel"; + + String securityProperty = null; + try { + MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID); + securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY); + } catch (UnsupportedSchemeException e) { + e.printStackTrace(); + } + if (securityProperty == null) { + p.resolve(widevineLevel); + return; + } + + switch (securityProperty) { + case WIDEVINE_SECURITY_LEVEL_1: { + widevineLevel = 1; + break; + } + case WIDEVINE_SECURITY_LEVEL_2: { + widevineLevel = 2; + break; + } + case WIDEVINE_SECURITY_LEVEL_3: { + widevineLevel = 3; + break; + } + default: { + // widevineLevel 0 + break; + } + } + } + p.resolve(widevineLevel); + } + + @SuppressLint("ObsoleteSdkInt") + @ReactMethod + public void isCodecSupported(String mimeType, int width, int height, Promise p) { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + MediaCodecList mRegularCodecs = new MediaCodecList(MediaCodecList.REGULAR_CODECS); + MediaFormat format = MediaFormat.createVideoFormat(mimeType, width, height); + String codecName = mRegularCodecs.findDecoderForFormat(format); + if (codecName == null) { + p.resolve(false); + } else { + p.resolve(true); + } + } else { + p.resolve(false); + } + } + + + @ReactMethod + public void isHEVCSupported(Promise p) { + isCodecSupported("video/hevc", 1920, 1080, p); + } + + public VideoDecoderPropertiesModule(ReactApplicationContext reactContext) { + super(reactContext); + this.reactContext = reactContext; + } + +} From 8408664600d4b1316bcac13e1d50756b84074cf1 Mon Sep 17 00:00:00 2001 From: olivier bouillet Date: Thu, 23 Jun 2022 22:54:47 +0200 Subject: [PATCH 04/35] feat(android): add sample to test decoder capabilities --- examples/basic/src/VideoPlayer.android.tsx | 39 +++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/examples/basic/src/VideoPlayer.android.tsx b/examples/basic/src/VideoPlayer.android.tsx index 0ca36fb6..ef53c752 100644 --- a/examples/basic/src/VideoPlayer.android.tsx +++ b/examples/basic/src/VideoPlayer.android.tsx @@ -16,7 +16,7 @@ import { import { Picker } from '@react-native-picker/picker' -import Video, { TextTrackType } from 'react-native-video'; +import Video, { VideoDecoderProperties, TextTrackType } from 'react-native-video'; class VideoPlayer extends Component { @@ -77,6 +77,28 @@ class VideoPlayer extends Component { video: Video; seekPanResponder: PanResponder | undefined; + popupInfo = () => { + VideoDecoderProperties.getWidevineLevel().then((widevineLevel: number) => { + VideoDecoderProperties.isHEVCSupported().then((hevcSupported: boolean) => { + VideoDecoderProperties.isCodecSupported('video/avc', 1920, 1080).then( + (avcSupported: boolean) => { + this.toast( + true, + 'Widevine level: ' + + widevineLevel + + '\n hevc: ' + + (hevcSupported ? '' : 'NOT') + + 'supported' + + '\n avc: ' + + (avcSupported ? '' : 'NOT') + + 'supported', + ) + }, + ) + }) + }) + } + onLoad = (data: any) => { this.setState({ duration: data.duration, loading: false, }); this.onAudioTracks(data.audioTracks) @@ -288,6 +310,18 @@ class VideoPlayer extends Component { ) } + renderInfoControl() { + return ( + { + this.popupInfo() + }} + > + {'decoderInfo'} + + ) + } + renderFullScreenControl() { return ( + + {this.renderInfoControl()} + {this.renderPause()} {this.renderRepeatModeControl()} From b10de93128167fad1630fba4d9f18ea2e304fd08 Mon Sep 17 00:00:00 2001 From: olivier bouillet Date: Thu, 23 Jun 2022 23:51:52 +0200 Subject: [PATCH 05/35] fix(android): ensure we don't disable playback when player is ENDED (issue #2690) --- .../java/com/brentvatne/exoplayer/ReactExoplayerView.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 3dccad93..775067bb 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -815,7 +815,10 @@ class ReactExoplayerView extends FrameLayout implements player.setPlayWhenReady(true); } } else { - player.setPlayWhenReady(false); + // ensure playback is not ENDED, else it will trigger another ended event + if (player.getPlaybackState() != Player.STATE_ENDED) { + player.setPlayWhenReady(false); + } } } From b64c7dbea5f0d9479267e10d1c125dc26cb66dd8 Mon Sep 17 00:00:00 2001 From: olivier bouillet Date: Tue, 5 Jul 2022 23:58:30 +0200 Subject: [PATCH 06/35] feat: add support of subtitles style configuration --- API.md | 18 +++++++++ Video.js | 7 ++++ .../java/com/brentvatne/ReactBridgeUtils.java | 22 +++++++++++ .../brentvatne/exoplayer/ExoPlayerView.java | 11 ++++++ .../exoplayer/ReactExoplayerView.java | 4 ++ .../exoplayer/ReactExoplayerViewManager.java | 7 ++++ .../brentvatne/exoplayer/SubtitleStyle.java | 38 +++++++++++++++++++ 7 files changed, 107 insertions(+) create mode 100644 android/src/main/java/com/brentvatne/ReactBridgeUtils.java create mode 100644 android/src/main/java/com/brentvatne/exoplayer/SubtitleStyle.java diff --git a/API.md b/API.md index 9ac52616..eb1f2eb0 100644 --- a/API.md +++ b/API.md @@ -304,6 +304,7 @@ var styles = StyleSheet.create({ |[selectedTextTrack](#selectedtexttrack)|Android, iOS| |[selectedVideoTrack](#selectedvideotrack)|Android| |[source](#source)|All| +|[subtitleStyle](#subtitleStyle)|Android| |[textTracks](#texttracks)|Android, iOS| |[trackId](#trackId)|Android| |[useTextureView](#usetextureview)|Android| @@ -835,6 +836,23 @@ The following other types are supported on some platforms, but aren't fully docu `content://, ms-appx://, ms-appdata://, assets-library://` +#### subtitleStyle + +Property | Description | Platforms +--- | --- | --- +fontSizeTrack | Adjust the font size of the subtitles. Default: font size of the device | Android +paddingTop | Adjust the top padding of the subtitles. Default: 0| Android +paddingBottom | Adjust the bottom padding of the subtitles. Default: 0| Android +paddingLeft | Adjust the left padding of the subtitles. Default: 0| Android +paddingRight | Adjust the right padding of the subtitles. Default: 0| Android + + +Example: + +``` +subtitleStyle={{ paddingBottom: 50, fontSize: 20 }} +``` + #### textTracks Load one or more "sidecar" text tracks. This takes an array of objects representing each track. Each object should have the format: diff --git a/Video.js b/Video.js index dad262b9..f3d96278 100644 --- a/Video.js +++ b/Video.js @@ -489,6 +489,13 @@ Video.propTypes = { fullscreenAutorotate: PropTypes.bool, fullscreenOrientation: PropTypes.oneOf(['all', 'landscape', 'portrait']), progressUpdateInterval: PropTypes.number, + subtitleStyle: PropTypes.shape({ + paddingTop: PropTypes.number, + paddingBottom: PropTypes.number, + paddingLeft: PropTypes.number, + paddingRight: PropTypes.number, + fontSize: PropTypes.number, + }), useTextureView: PropTypes.bool, useSecureView: PropTypes.bool, hideShutterView: PropTypes.bool, diff --git a/android/src/main/java/com/brentvatne/ReactBridgeUtils.java b/android/src/main/java/com/brentvatne/ReactBridgeUtils.java new file mode 100644 index 00000000..c3391283 --- /dev/null +++ b/android/src/main/java/com/brentvatne/ReactBridgeUtils.java @@ -0,0 +1,22 @@ +package com.brentvatne; + +import com.facebook.react.bridge.ReadableMap; + +/* +* This file define static helpers to parse in an easier way input props + */ +public class ReactBridgeUtils { + /* + retrieve key from map as int. fallback is returned if not available + */ + static public int safeGetInt(ReadableMap map, String key, int fallback) { + return map != null && map.hasKey(key) && !map.isNull(key) ? map.getInt(key) : fallback; + } + + /* + retrieve key from map as double. fallback is returned if not available + */ + static public double safeGetDouble(ReadableMap map, String key, double fallback) { + return map != null && map.hasKey(key) && !map.isNull(key) ? map.getDouble(key) : fallback; + } +} diff --git a/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java index a6cd1c4f..8c97298a 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java @@ -5,6 +5,7 @@ import android.content.Context; import androidx.core.content.ContextCompat; import android.util.AttributeSet; import android.util.Log; +import android.util.TypedValue; import android.view.Gravity; import android.view.SurfaceView; import android.view.TextureView; @@ -100,6 +101,16 @@ public final class ExoPlayerView extends FrameLayout { player.setVideoSurfaceView((SurfaceView) surfaceView); } } + public void setSubtitleStyle(SubtitleStyle style) { + // ensure we reset subtile style before reapplying it + subtitleLayout.setUserDefaultStyle(); + subtitleLayout.setUserDefaultTextSize(); + + if (style.getFontSize() > 0) { + subtitleLayout.setFixedTextSize(TypedValue.COMPLEX_UNIT_SP, style.getFontSize()); + } + subtitleLayout.setPadding(style.getPaddingLeft(), style.getPaddingTop(), style.getPaddingRight(), style.getPaddingBottom()); + } private void updateSurfaceView() { View view; diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 3dccad93..7e77c4e9 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -1838,4 +1838,8 @@ class ReactExoplayerView extends FrameLayout implements } } } + + public void setSubtitleStyle(SubtitleStyle style) { + exoPlayerView.setSubtitleStyle(style); + } } diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java index 3744fcae..ce1d6a8c 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java @@ -79,6 +79,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager Date: Wed, 27 Jul 2022 21:13:47 +0800 Subject: [PATCH 07/35] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20support=20came?= =?UTF-8?q?ra=20video=20for=20swift?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Video/Features/RCTVideoUtils.swift | 15 ++++++++++++++- ios/Video/RCTVideo.swift | 18 ++++++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/ios/Video/Features/RCTVideoUtils.swift b/ios/Video/Features/RCTVideoUtils.swift index d8ec8677..46cce42a 100644 --- a/ios/Video/Features/RCTVideoUtils.swift +++ b/ios/Video/Features/RCTVideoUtils.swift @@ -1,5 +1,6 @@ import AVFoundation import Promises +import Photos /*! * Collection of pure functions @@ -264,8 +265,20 @@ enum RCTVideoUtils { } } + static func preparePHAsset(uri: String) -> Promise { + return Promise(on: .global()) { fulfill, reject in + let assetId = String(uri[uri.index(uri.startIndex, offsetBy: "ph://".count)...]) + let phAsset = PHAsset.fetchAssets(withLocalIdentifiers: [assetId], options: nil).firstObject + let options = PHVideoRequestOptions() + options.isNetworkAccessAllowed = true + PHCachingImageManager().requestAVAsset(forVideo: phAsset!, options: options) { data, _, _ in + fulfill(data) + } + } + } + static func prepareAsset(source:VideoSource) -> (asset:AVURLAsset?, assetOptions:NSMutableDictionary?)? { - guard source.uri != nil && source.uri != "" else { return nil } + guard let sourceUri = source.uri, sourceUri != "" else { return nil } var asset:AVURLAsset! let bundlePath = Bundle.main.path(forResource: source.uri, ofType: source.type) ?? "" let url = source.isNetwork || source.isAsset diff --git a/ios/Video/RCTVideo.swift b/ios/Video/RCTVideo.swift index 59973a36..a339aff4 100644 --- a/ios/Video/RCTVideo.swift +++ b/ios/Video/RCTVideo.swift @@ -227,10 +227,20 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH RCTVideoUtils.delay() .then{ [weak self] in guard let self = self else {throw NSError(domain: "", code: 0, userInfo: nil)} - guard let source = self._source, - let assetResult = RCTVideoUtils.prepareAsset(source: source), - let asset = assetResult.asset, - let assetOptions = assetResult.assetOptions else { + guard let source = self._source else { + DebugLog("The source not exist") + throw NSError(domain: "", code: 0, userInfo: nil) + } + if let uri = source.uri, uri.starts(with: "ph://") { + return Promise { + RCTVideoUtils.preparePHAsset(uri: uri).then { asset in + return self.playerItemPrepareText(asset:asset, assetOptions:nil) + } + } + } + guard let assetResult = RCTVideoUtils.prepareAsset(source: source), + let asset = assetResult.asset, + let assetOptions = assetResult.assetOptions else { DebugLog("Could not find video URL in source '\(self._source)'") throw NSError(domain: "", code: 0, userInfo: nil) } From cee650c84cb37f31b2596ae1181ea36f0c80bb5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=9B=A6?= Date: Wed, 27 Jul 2022 21:34:08 +0800 Subject: [PATCH 08/35] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20exception=20?= =?UTF-8?q?catch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Video/Features/RCTVideoUtils.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ios/Video/Features/RCTVideoUtils.swift b/ios/Video/Features/RCTVideoUtils.swift index 46cce42a..50df8e3f 100644 --- a/ios/Video/Features/RCTVideoUtils.swift +++ b/ios/Video/Features/RCTVideoUtils.swift @@ -268,10 +268,13 @@ enum RCTVideoUtils { static func preparePHAsset(uri: String) -> Promise { return Promise(on: .global()) { fulfill, reject in let assetId = String(uri[uri.index(uri.startIndex, offsetBy: "ph://".count)...]) - let phAsset = PHAsset.fetchAssets(withLocalIdentifiers: [assetId], options: nil).firstObject + guard let phAsset = PHAsset.fetchAssets(withLocalIdentifiers: [assetId], options: nil).firstObject else { + reject(NSError(domain: "", code: 0, userInfo: nil)) + return + } let options = PHVideoRequestOptions() options.isNetworkAccessAllowed = true - PHCachingImageManager().requestAVAsset(forVideo: phAsset!, options: options) { data, _, _ in + PHCachingImageManager().requestAVAsset(forVideo: phAsset, options: options) { data, _, _ in fulfill(data) } } From f990ec9de12977d87673f587b72d0987d6c61a0b Mon Sep 17 00:00:00 2001 From: olivier bouillet Date: Mon, 1 Aug 2022 15:51:10 +0200 Subject: [PATCH 09/35] fix: invalid doc path --- API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API.md b/API.md index 9ac52616..6d276cd0 100644 --- a/API.md +++ b/API.md @@ -436,7 +436,7 @@ Determines if the player needs to throw an error when connection is lost or not Platforms: Android ### DRM -To setup DRM please follow [this guide](./DRM.md) +To setup DRM please follow [this guide](./docs/DRM.md) Platforms: Android, iOS From edd0d4ec83f039bf7114ad35b4fbb8ea5f7a58ab Mon Sep 17 00:00:00 2001 From: olivier bouillet Date: Mon, 1 Aug 2022 15:51:57 +0200 Subject: [PATCH 10/35] chore: add warning in changelog to manage library upgrade to V6 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0778647..72d42d7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ ### Version 6.0.0-alpha.1 - Remove Android MediaPlayer support [#2724](https://github.com/react-native-video/react-native-video/pull/2724) + **WARNING**: when switching from older version to V6, you need to remove all refrerences of android-exoplayer. This android-exoplayer folder has been renamed to android. Exoplayer is now the only player implementation supported. + - Replace Image.propTypes with ImagePropTypes. [#2718](https://github.com/react-native-video/react-native-video/pull/2718) - Fix iOS build caused by type mismatch [#2720](https://github.com/react-native-video/react-native-video/pull/2720) - ERROR TypeError: undefined is not an object (evaluating '_reactNative.Image.propTypes.resizeMode') [#2714](https://github.com/react-native-video/react-native-video/pull/2714) From efc94d7f2cfa0cb9203c3a8c0aa49f6abfa82557 Mon Sep 17 00:00:00 2001 From: Matthew Leffler Date: Mon, 1 Aug 2022 16:07:25 -0600 Subject: [PATCH 11/35] docs: Fix page path --- API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API.md b/API.md index 9ac52616..6d276cd0 100644 --- a/API.md +++ b/API.md @@ -436,7 +436,7 @@ Determines if the player needs to throw an error when connection is lost or not Platforms: Android ### DRM -To setup DRM please follow [this guide](./DRM.md) +To setup DRM please follow [this guide](./docs/DRM.md) Platforms: Android, iOS From 1631e5de5230d1d18b12389c137537e6b602e425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=9B=A6?= Date: Tue, 2 Aug 2022 15:21:43 +0800 Subject: [PATCH 12/35] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20change=20cha?= =?UTF-8?q?ngelog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index adfb0da5..805868d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Fix being unable to disable sideloaded texttracks in the AVPlayer [#2679](https://github.com/react-native-video/react-native-video/pull/2679) - Fixed crash when iOS seek method called reject on the promise [#2743](https://github.com/react-native-video/react-native-video/pull/2743) - Fix maxBitRate property being ignored on Android [#2670](https://github.com/react-native-video/react-native-video/pull/2670) +- Fix crash when the source is a cameraroll [#2639] (https://github.com/react-native-video/react-native-video/pull/2639) ### Version 6.0.0-alpha.1 @@ -55,8 +56,6 @@ - Fixed `onReadyForDisplay` not being called [#2721](https://github.com/react-native-video/react-native-video/pull/2721) - Fix type of `_eventDispatcher` on iOS target to match `bridge.eventDispatcher()` [#2720](https://github.com/react-native-video/react-native-video/pull/2720) -- Fix crash when the source is a cameraroll [#2639] (https://github.com/react-native-video/react-native-video/pull/2639) - ### Version 5.2.0 - Fix for tvOS native audio menu language selector From e1987e561ab06e96b86396069492ee792943ab5a Mon Sep 17 00:00:00 2001 From: john Date: Fri, 5 Aug 2022 09:53:22 +0800 Subject: [PATCH 13/35] fix rctDelegate is nil --- ios/Video/RCTVideoPlayerViewController.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ios/Video/RCTVideoPlayerViewController.swift b/ios/Video/RCTVideoPlayerViewController.swift index 95c926af..e398e62f 100644 --- a/ios/Video/RCTVideoPlayerViewController.swift +++ b/ios/Video/RCTVideoPlayerViewController.swift @@ -19,8 +19,11 @@ class RCTVideoPlayerViewController: AVPlayerViewController { override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) - rctDelegate.videoPlayerViewControllerWillDismiss(playerViewController: self) - rctDelegate.videoPlayerViewControllerDidDismiss(playerViewController: self) + + if rctDelegate != nil { + rctDelegate.videoPlayerViewControllerWillDismiss(playerViewController: self) + rctDelegate.videoPlayerViewControllerDidDismiss(playerViewController: self) + } } #if !TARGET_OS_TV From f32da092b17b912f013da611358302addcea310d Mon Sep 17 00:00:00 2001 From: Olivier Bouillet <62574056+freeboub@users.noreply.github.com> Date: Sat, 6 Aug 2022 14:10:11 +0200 Subject: [PATCH 14/35] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 54296c23..223be5ae 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -10,10 +10,12 @@ assignees: '' # Bug ## Platform From 1a53c10c06534a0c2a22d0c6eebcc64cec701706 Mon Sep 17 00:00:00 2001 From: olivier bouillet Date: Sat, 20 Aug 2022 14:26:53 +0200 Subject: [PATCH 15/35] doc: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c9bef79..c8589cd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Version 6.0.0-alpha.2 +- Fix Android #2690 ensure onEnd is not sent twice [#2690](https://github.com/react-native-video/react-native-video/issues/2690) - Fix Exoplayer progress not reported when paused [#2664](https://github.com/react-native-video/react-native-video/pull/2664) - Call playbackRateChange onPlay and onPause [#1493](https://github.com/react-native-video/react-native-video/pull/1493) From 7fe3b28f26fa90d32a290a5154e1d978f848ec63 Mon Sep 17 00:00:00 2001 From: olivier bouillet Date: Sat, 20 Aug 2022 14:31:15 +0200 Subject: [PATCH 16/35] doc: update changeLog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1968e293..95b2a97e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Version 6.0.0-alpha.2 +- Feature add support of subtitle styling on android [#2759](https://github.com/react-native-video/react-native-video/pull/2759) - Fix Android #2690 ensure onEnd is not sent twice [#2690](https://github.com/react-native-video/react-native-video/issues/2690) - Fix Exoplayer progress not reported when paused [#2664](https://github.com/react-native-video/react-native-video/pull/2664) - Call playbackRateChange onPlay and onPause [#1493](https://github.com/react-native-video/react-native-video/pull/1493) From 0ff6d5f657e9d7cae109ccd1dc594d3af3e80fcd Mon Sep 17 00:00:00 2001 From: olivier bouillet Date: Sat, 20 Aug 2022 14:34:27 +0200 Subject: [PATCH 17/35] doc: update changeLog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95b2a97e..a7196459 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Version 6.0.0-alpha.2 +- Feature add new APIs to query supported features of device decoder (widevine level & codec capabilities) on android [#2740](https://github.com/react-native-video/react-native-video/pull/2740) - Feature add support of subtitle styling on android [#2759](https://github.com/react-native-video/react-native-video/pull/2759) - Fix Android #2690 ensure onEnd is not sent twice [#2690](https://github.com/react-native-video/react-native-video/issues/2690) - Fix Exoplayer progress not reported when paused [#2664](https://github.com/react-native-video/react-native-video/pull/2664) From 271206940843418e7cb266f252160e08c933f2f9 Mon Sep 17 00:00:00 2001 From: olivier bouillet Date: Sat, 20 Aug 2022 15:12:40 +0200 Subject: [PATCH 18/35] chore(android): change test logic for simplier code --- .../react/VideoDecoderPropertiesModule.java | 90 ++++++++++--------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.java b/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.java index 12ae388c..6622e7f9 100644 --- a/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.java +++ b/android/src/main/java/com/brentvatne/react/VideoDecoderPropertiesModule.java @@ -33,42 +33,44 @@ public class VideoDecoderPropertiesModule extends ReactContextBaseJavaModule { public void getWidevineLevel(Promise p) { int widevineLevel = 0; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) { - final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL); - final String WIDEVINE_SECURITY_LEVEL_1 = "L1"; - final String WIDEVINE_SECURITY_LEVEL_2 = "L2"; - final String WIDEVINE_SECURITY_LEVEL_3 = "L3"; - final String SECURITY_LEVEL_PROPERTY = "securityLevel"; + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) { + p.resolve(widevineLevel); + return; + } + final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL); + final String WIDEVINE_SECURITY_LEVEL_1 = "L1"; + final String WIDEVINE_SECURITY_LEVEL_2 = "L2"; + final String WIDEVINE_SECURITY_LEVEL_3 = "L3"; + final String SECURITY_LEVEL_PROPERTY = "securityLevel"; - String securityProperty = null; - try { - MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID); - securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY); - } catch (UnsupportedSchemeException e) { - e.printStackTrace(); - } - if (securityProperty == null) { - p.resolve(widevineLevel); - return; - } + String securityProperty = null; + try { + MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID); + securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY); + } catch (UnsupportedSchemeException e) { + e.printStackTrace(); + } + if (securityProperty == null) { + p.resolve(widevineLevel); + return; + } - switch (securityProperty) { - case WIDEVINE_SECURITY_LEVEL_1: { - widevineLevel = 1; - break; - } - case WIDEVINE_SECURITY_LEVEL_2: { - widevineLevel = 2; - break; - } - case WIDEVINE_SECURITY_LEVEL_3: { - widevineLevel = 3; - break; - } - default: { - // widevineLevel 0 - break; - } + switch (securityProperty) { + case WIDEVINE_SECURITY_LEVEL_1: { + widevineLevel = 1; + break; + } + case WIDEVINE_SECURITY_LEVEL_2: { + widevineLevel = 2; + break; + } + case WIDEVINE_SECURITY_LEVEL_3: { + widevineLevel = 3; + break; + } + default: { + // widevineLevel 0 + break; } } p.resolve(widevineLevel); @@ -77,17 +79,17 @@ public class VideoDecoderPropertiesModule extends ReactContextBaseJavaModule { @SuppressLint("ObsoleteSdkInt") @ReactMethod public void isCodecSupported(String mimeType, int width, int height, Promise p) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { - MediaCodecList mRegularCodecs = new MediaCodecList(MediaCodecList.REGULAR_CODECS); - MediaFormat format = MediaFormat.createVideoFormat(mimeType, width, height); - String codecName = mRegularCodecs.findDecoderForFormat(format); - if (codecName == null) { - p.resolve(false); - } else { - p.resolve(true); - } - } else { + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) { p.resolve(false); + return; + } + MediaCodecList mRegularCodecs = new MediaCodecList(MediaCodecList.REGULAR_CODECS); + MediaFormat format = MediaFormat.createVideoFormat(mimeType, width, height); + String codecName = mRegularCodecs.findDecoderForFormat(format); + if (codecName == null) { + p.resolve(false); + } else { + p.resolve(true); } } From 32449cd6d8aef5ffcea7879fdc79b2b14ed64911 Mon Sep 17 00:00:00 2001 From: olivier bouillet Date: Sun, 21 Aug 2022 14:22:15 +0200 Subject: [PATCH 19/35] doc: fix typo --- API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API.md b/API.md index a5e9e089..0ce67252 100644 --- a/API.md +++ b/API.md @@ -431,7 +431,7 @@ Platforms: Android, iOS #### disableFocus Determines whether video audio should override background music/audio in Android devices. -* ** false (default)** - Override background audio/music +* **false (default)** - Override background audio/music * **true** - Let background audio/music from other apps play Platforms: Android From b144a50f41bdc6ea389767f8c4d0076d773aee70 Mon Sep 17 00:00:00 2001 From: wood1986 <5212215+wood1986@users.noreply.github.com> Date: Thu, 14 Jul 2022 11:10:18 -0700 Subject: [PATCH 20/35] feat: add full screen support based on expo-av implementation --- .../exoplayer/FullScreenPlayerView.java | 71 +++++++++++++++++++ .../exoplayer/ReactExoplayerView.java | 11 ++- .../res/layout/exo_player_control_view.xml | 8 +++ android/src/main/res/values/styles.xml | 7 ++ 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java create mode 100644 android/src/main/res/values/styles.xml diff --git a/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java new file mode 100644 index 00000000..72e09aae --- /dev/null +++ b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java @@ -0,0 +1,71 @@ +package com.brentvatne.exoplayer; + +import android.app.Dialog; +import android.content.Context; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageButton; + +import com.google.android.exoplayer2.ui.PlayerControlView; + +public class FullScreenPlayerView extends Dialog { + private final PlayerControlView playerControlView; + private final ExoPlayerView exoPlayerView; + private ViewGroup parent; + private final FrameLayout containerView; + + public FullScreenPlayerView(Context context, ExoPlayerView exoPlayerView, PlayerControlView playerControlView) { + super(context, android.R.style.Theme_Black_NoTitleBar_Fullscreen); + this.playerControlView = playerControlView; + this.exoPlayerView = exoPlayerView; + containerView = new FrameLayout(context); + setContentView(containerView, generateDefaultLayoutParams()); + } + + @Override + protected void onStart() { + parent = (FrameLayout)(exoPlayerView.getParent()); + + parent.removeView(exoPlayerView); + containerView.addView(exoPlayerView, generateDefaultLayoutParams()); + + if (playerControlView != null) { + ImageButton imageButton = playerControlView.findViewById(com.brentvatne.react.R.id.exo_fullscreen); + imageButton.setBackgroundResource(com.google.android.exoplayer2.ui.R.drawable.exo_icon_fullscreen_exit); + imageButton.setContentDescription(getContext().getString(com.google.android.exoplayer2.ui.R.string.exo_controls_fullscreen_exit_description)); + parent.removeView(playerControlView); + containerView.addView(playerControlView, generateDefaultLayoutParams()); + + } + + super.onStart(); + } + + @Override + protected void onStop() { + containerView.removeView(exoPlayerView); + parent.addView(exoPlayerView, generateDefaultLayoutParams()); + + if (playerControlView != null) { + ImageButton imageButton = playerControlView.findViewById(com.brentvatne.react.R.id.exo_fullscreen); + imageButton.setBackgroundResource(com.google.android.exoplayer2.ui.R.drawable.exo_icon_fullscreen_enter); + imageButton.setContentDescription(getContext().getString(com.google.android.exoplayer2.ui.R.string.exo_controls_fullscreen_enter_description)); + containerView.removeView(playerControlView); + parent.addView(playerControlView, generateDefaultLayoutParams()); + } + + parent.requestLayout(); + parent = null; + + super.onStop(); + } + + private FrameLayout.LayoutParams generateDefaultLayoutParams() { + FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT + ); + layoutParams.setMargins(0, 0, 0, 0); + return layoutParams; + } +} diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 9a334132..c80d86f5 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -140,6 +140,7 @@ class ReactExoplayerView extends FrameLayout implements private Player.Listener eventListener; private ExoPlayerView exoPlayerView; + private FullScreenPlayerView fullScreenPlayerView; private DataSource.Factory mediaDataSourceFactory; private ExoPlayer player; @@ -399,6 +400,10 @@ class ReactExoplayerView extends FrameLayout implements } }); + //Handling the fullScreenButton click event + ImageButton fullScreenButton = playerControlView.findViewById(R.id.exo_fullscreen); + fullScreenButton.setOnClickListener(v -> setFullscreen(!isFullscreen)); + // Invoking onPlaybackStateChanged and onPlayWhenReadyChanged events for Player eventListener = new Player.Listener() { @Override @@ -664,6 +669,7 @@ class ReactExoplayerView extends FrameLayout implements setControls(controls); applyModifiers(); startBufferCheckTimer(); + fullScreenPlayerView = new FullScreenPlayerView(getContext(), exoPlayerView, playerControlView); } private DrmSessionManager buildDrmSessionManager(UUID uuid, String licenseUrl, String[] keyRequestPropertiesArray) throws UnsupportedDrmException { @@ -1770,14 +1776,15 @@ class ReactExoplayerView extends FrameLayout implements | SYSTEM_UI_FLAG_FULLSCREEN; } eventEmitter.fullscreenWillPresent(); - decorView.setSystemUiVisibility(uiOptions); + fullScreenPlayerView.show(); eventEmitter.fullscreenDidPresent(); } else { uiOptions = View.SYSTEM_UI_FLAG_VISIBLE; eventEmitter.fullscreenWillDismiss(); - decorView.setSystemUiVisibility(uiOptions); + fullScreenPlayerView.dismiss(); eventEmitter.fullscreenDidDismiss(); } + post(() -> decorView.setSystemUiVisibility(uiOptions)); } public void setUseTextureView(boolean useTextureView) { diff --git a/android/src/main/res/layout/exo_player_control_view.xml b/android/src/main/res/layout/exo_player_control_view.xml index becee6a9..19440912 100644 --- a/android/src/main/res/layout/exo_player_control_view.xml +++ b/android/src/main/res/layout/exo_player_control_view.xml @@ -71,6 +71,14 @@ android:paddingRight="4dp" android:includeFontPadding="false" android:textColor="#FFBEBEBE"/> + + diff --git a/android/src/main/res/values/styles.xml b/android/src/main/res/values/styles.xml new file mode 100644 index 00000000..3459d9d6 --- /dev/null +++ b/android/src/main/res/values/styles.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file From 470ca7bf60256b8cf97d0d3db9d91eaf2e034e3d Mon Sep 17 00:00:00 2001 From: wood1986 <5212215+wood1986@users.noreply.github.com> Date: Thu, 14 Jul 2022 15:50:25 -0700 Subject: [PATCH 21/35] WIP --- .../java/com/brentvatne/exoplayer/FullScreenPlayerView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java index 72e09aae..5633829c 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java @@ -31,7 +31,7 @@ public class FullScreenPlayerView extends Dialog { if (playerControlView != null) { ImageButton imageButton = playerControlView.findViewById(com.brentvatne.react.R.id.exo_fullscreen); - imageButton.setBackgroundResource(com.google.android.exoplayer2.ui.R.drawable.exo_icon_fullscreen_exit); + imageButton.setImageResource(com.google.android.exoplayer2.ui.R.drawable.exo_icon_fullscreen_exit); imageButton.setContentDescription(getContext().getString(com.google.android.exoplayer2.ui.R.string.exo_controls_fullscreen_exit_description)); parent.removeView(playerControlView); containerView.addView(playerControlView, generateDefaultLayoutParams()); @@ -48,7 +48,7 @@ public class FullScreenPlayerView extends Dialog { if (playerControlView != null) { ImageButton imageButton = playerControlView.findViewById(com.brentvatne.react.R.id.exo_fullscreen); - imageButton.setBackgroundResource(com.google.android.exoplayer2.ui.R.drawable.exo_icon_fullscreen_enter); + imageButton.setImageResource(com.google.android.exoplayer2.ui.R.drawable.exo_icon_fullscreen_enter); imageButton.setContentDescription(getContext().getString(com.google.android.exoplayer2.ui.R.string.exo_controls_fullscreen_enter_description)); containerView.removeView(playerControlView); parent.addView(playerControlView, generateDefaultLayoutParams()); From 810c62407f4356ed724f3016ccb5f4418eb616f3 Mon Sep 17 00:00:00 2001 From: wood1986 <5212215+wood1986@users.noreply.github.com> Date: Thu, 11 Aug 2022 19:07:10 -0700 Subject: [PATCH 22/35] WIP --- .../main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java | 1 - 1 file changed, 1 deletion(-) diff --git a/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java index 5633829c..4a7edb1d 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java @@ -35,7 +35,6 @@ public class FullScreenPlayerView extends Dialog { imageButton.setContentDescription(getContext().getString(com.google.android.exoplayer2.ui.R.string.exo_controls_fullscreen_exit_description)); parent.removeView(playerControlView); containerView.addView(playerControlView, generateDefaultLayoutParams()); - } super.onStart(); From 622f9d3f3f2d5bb2bb5568eee740f2972685f255 Mon Sep 17 00:00:00 2001 From: wood1986 <5212215+wood1986@users.noreply.github.com> Date: Thu, 18 Aug 2022 01:12:08 -0700 Subject: [PATCH 23/35] fix: fix the hardware back button --- .../brentvatne/exoplayer/FullScreenPlayerView.java | 12 +++++++++++- .../com/brentvatne/exoplayer/ReactExoplayerView.java | 9 ++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java index 4a7edb1d..f57bb964 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java @@ -6,6 +6,8 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageButton; +import androidx.activity.OnBackPressedCallback; + import com.google.android.exoplayer2.ui.PlayerControlView; public class FullScreenPlayerView extends Dialog { @@ -13,15 +15,23 @@ public class FullScreenPlayerView extends Dialog { private final ExoPlayerView exoPlayerView; private ViewGroup parent; private final FrameLayout containerView; + private final OnBackPressedCallback onBackPressedCallback; - public FullScreenPlayerView(Context context, ExoPlayerView exoPlayerView, PlayerControlView playerControlView) { + public FullScreenPlayerView(Context context, ExoPlayerView exoPlayerView, PlayerControlView playerControlView, OnBackPressedCallback onBackPressedCallback) { super(context, android.R.style.Theme_Black_NoTitleBar_Fullscreen); this.playerControlView = playerControlView; this.exoPlayerView = exoPlayerView; + this.onBackPressedCallback = onBackPressedCallback; containerView = new FrameLayout(context); setContentView(containerView, generateDefaultLayoutParams()); } + @Override + public void onBackPressed() { + super.onBackPressed(); + onBackPressedCallback.handleOnBackPressed(); + } + @Override protected void onStart() { parent = (FrameLayout)(exoPlayerView.getParent()); diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index c80d86f5..511437da 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -17,6 +17,8 @@ import android.view.accessibility.CaptioningManager; import android.widget.FrameLayout; import android.widget.ImageButton; +import androidx.activity.OnBackPressedCallback; + import com.brentvatne.react.R; import com.brentvatne.receiver.AudioBecomingNoisyReceiver; import com.brentvatne.receiver.BecomingNoisyListener; @@ -669,7 +671,12 @@ class ReactExoplayerView extends FrameLayout implements setControls(controls); applyModifiers(); startBufferCheckTimer(); - fullScreenPlayerView = new FullScreenPlayerView(getContext(), exoPlayerView, playerControlView); + fullScreenPlayerView = new FullScreenPlayerView(getContext(), exoPlayerView, playerControlView, new OnBackPressedCallback(true) { + @Override + public void handleOnBackPressed() { + setFullscreen(false); + } + }); } private DrmSessionManager buildDrmSessionManager(UUID uuid, String licenseUrl, String[] keyRequestPropertiesArray) throws UnsupportedDrmException { From a79c30eaba277db4cd13b3515567c17b7a09ee58 Mon Sep 17 00:00:00 2001 From: wood1986 <5212215+wood1986@users.noreply.github.com> Date: Tue, 23 Aug 2022 13:11:10 -0700 Subject: [PATCH 24/35] fix: fix control not showing up at very first touch --- .../java/com/brentvatne/exoplayer/ReactExoplayerView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 511437da..d1a7d80c 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -370,7 +370,6 @@ class ReactExoplayerView extends FrameLayout implements // Setting the player for the playerControlView playerControlView.setPlayer(player); - playerControlView.show(); playPauseControlContainer = playerControlView.findViewById(R.id.exo_play_pause_container); // Invoking onClick event for exoplayerView @@ -448,6 +447,7 @@ class ReactExoplayerView extends FrameLayout implements removeViewAt(indexOfPC); } addView(playerControlView, 1, layoutParams); + reLayout(playerControlView); } /** @@ -595,7 +595,7 @@ class ReactExoplayerView extends FrameLayout implements new DefaultRenderersFactory(getContext()) .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF); player = new ExoPlayer.Builder(getContext(), renderersFactory) - .setTrackSelector​(self.trackSelector) + .setTrackSelector(self.trackSelector) .setBandwidthMeter(bandwidthMeter) .setLoadControl(loadControl) .build(); From f558d05923bb9f487daf5c82b4201ef63bb25498 Mon Sep 17 00:00:00 2001 From: Gabriel Rivero Date: Fri, 26 Aug 2022 10:32:22 -0400 Subject: [PATCH 25/35] upgrade exoplayer --- android/build.gradle | 4 ++-- .../brentvatne/exoplayer/ExoPlayerView.java | 6 +++--- .../exoplayer/ReactExoplayerView.java | 21 +++++++++++-------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index a93e7599..16c54864 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -33,7 +33,7 @@ repositories { dependencies { implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" - implementation('com.google.android.exoplayer:exoplayer:2.17.1') { + implementation('com.google.android.exoplayer:exoplayer:2.18.1') { exclude group: 'com.android.support' } @@ -42,7 +42,7 @@ dependencies { implementation "androidx.core:core:1.1.0" implementation "androidx.media:media:1.1.0" - implementation('com.google.android.exoplayer:extension-okhttp:2.17.1') { + implementation('com.google.android.exoplayer:extension-okhttp:2.18.1') { exclude group: 'com.squareup.okhttp3', module: 'okhttp' } implementation 'com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}' diff --git a/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java index a6cd1c4f..ce52f7df 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java @@ -18,7 +18,7 @@ import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Timeline; -import com.google.android.exoplayer2.TracksInfo; +import com.google.android.exoplayer2.Tracks; import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.ui.SubtitleView; @@ -230,7 +230,7 @@ public final class ExoPlayerView extends FrameLayout { @Override public void onCues(List cues) { - subtitleLayout.onCues(cues); + subtitleLayout.setCues(cues); } // ExoPlayer.VideoListener implementation @@ -284,7 +284,7 @@ public final class ExoPlayerView extends FrameLayout { } @Override - public void onTracksInfoChanged(TracksInfo tracksInfo) { + public void onTracksChanged(Tracks tracks) { updateForCurrentTrackSelections(); } diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 9a790fdc..448d1946 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -42,8 +42,9 @@ import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Timeline; -import com.google.android.exoplayer2.TracksInfo; +import com.google.android.exoplayer2.Tracks; import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; +import com.google.android.exoplayer2.drm.DefaultDrmSessionManagerProvider; import com.google.android.exoplayer2.drm.DrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManagerProvider; @@ -72,8 +73,8 @@ import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector; import com.google.android.exoplayer2.trackselection.ExoTrackSelection; -import com.google.android.exoplayer2.trackselection.TrackSelectionOverrides; -import com.google.android.exoplayer2.trackselection.TrackSelectionOverrides.TrackSelectionOverride; +import com.google.android.exoplayer2.trackselection.TrackSelectionParameters; +import com.google.android.exoplayer2.trackselection.TrackSelectionOverride; import com.google.android.exoplayer2.ui.PlayerControlView; import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DataSource; @@ -548,7 +549,7 @@ class ReactExoplayerView extends FrameLayout implements private void initializePlayerCore(ReactExoplayerView self) { ExoTrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(); - self.trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); + self.trackSelector = new DefaultTrackSelector(getContext(), videoTrackSelectionFactory); self.trackSelector.setParameters(trackSelector.buildUponParameters() .setMaxVideoBitrate(maxBitRate == 0 ? Integer.MAX_VALUE : maxBitRate)); @@ -698,6 +699,8 @@ class ReactExoplayerView extends FrameLayout implements return drmSessionManager; } }; + } else { + drmProvider = new DefaultDrmSessionManagerProvider(); } switch (type) { case C.TYPE_SS: @@ -1253,7 +1256,7 @@ class ReactExoplayerView extends FrameLayout implements } @Override - public void onTracksInfoChanged(TracksInfo tracksInfo) { + public void onTracksChanged(Tracks tracks) { // Do nothing. } @@ -1565,10 +1568,10 @@ class ReactExoplayerView extends FrameLayout implements TrackSelectionOverride selectionOverride = new TrackSelectionOverride(groups.get(groupIndex), tracks); DefaultTrackSelector.Parameters selectionParameters = trackSelector.getParameters() - .buildUpon() - .setRendererDisabled(rendererIndex, false) - .setTrackSelectionOverrides(new TrackSelectionOverrides.Builder().addOverride(selectionOverride).build()) - .build(); + .buildUpon() + .setRendererDisabled(rendererIndex, false) + .addOverride(selectionOverride) + .build(); trackSelector.setParameters(selectionParameters); } From d490c300efe13aa3989d7e60d6cbc070c81e90b7 Mon Sep 17 00:00:00 2001 From: Karl Date: Sat, 3 Sep 2022 08:29:46 +0100 Subject: [PATCH 26/35] Update API.md --- API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API.md b/API.md index 0ce67252..48401b78 100644 --- a/API.md +++ b/API.md @@ -214,7 +214,7 @@ Follow the manual linking instuctions for React Native Windows 0.62 above, but s ## Examples -Run `yarn xbasic install` before running any of the examples. +Run `yarn xbasic install` in the root directory before running any of the examples. ### iOS Example ``` From 6e6ae9d7c900df7c19413e1380205f5ed41af0cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stipe=20Perkovi=C4=87?= Date: Tue, 6 Sep 2022 12:13:54 +0200 Subject: [PATCH 27/35] IOS: fix ui frame drop on load --- ios/Video/RCTVideo.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ios/Video/RCTVideo.swift b/ios/Video/RCTVideo.swift index a339aff4..a003f814 100644 --- a/ios/Video/RCTVideo.swift +++ b/ios/Video/RCTVideo.swift @@ -274,7 +274,10 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH self._playerItem?.preferredPeakBitRate = Double(maxBitRate) } - self._player = AVPlayer(playerItem: self._playerItem) + self._player = AVPlayer() + DispatchQueue.global(qos: .default).async { + self._player?.replaceCurrentItem(with: playerItem) + } self._playerObserver.player = self._player self.applyModifiers() self._player?.actionAtItemEnd = .none From 02081857f03c7a9b567967fa527f7c0444d7b85e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stipe=20Perkovi=C4=87?= Date: Tue, 6 Sep 2022 12:55:00 +0200 Subject: [PATCH 28/35] fix indent --- ios/Video/RCTVideo.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Video/RCTVideo.swift b/ios/Video/RCTVideo.swift index a003f814..f482ff7c 100644 --- a/ios/Video/RCTVideo.swift +++ b/ios/Video/RCTVideo.swift @@ -274,7 +274,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH self._playerItem?.preferredPeakBitRate = Double(maxBitRate) } - self._player = AVPlayer() + self._player = AVPlayer() DispatchQueue.global(qos: .default).async { self._player?.replaceCurrentItem(with: playerItem) } From 98380f0fb9fe54532359abbecfa97aebcb4606f3 Mon Sep 17 00:00:00 2001 From: Karl Date: Tue, 6 Sep 2022 15:34:26 +0100 Subject: [PATCH 29/35] Docs: Add note to `disableFocus` explaining that it allows multiple videos to play. --- API.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/API.md b/API.md index 48401b78..d9153f77 100644 --- a/API.md +++ b/API.md @@ -433,7 +433,9 @@ Platforms: Android, iOS Determines whether video audio should override background music/audio in Android devices. * **false (default)** - Override background audio/music * **true** - Let background audio/music from other apps play - + +Note: Allows multiple videos to play if set to `true`. If `false`, when one video is playing and another is started, the first video will be paused. + Platforms: Android #### disableDisconnectError From a1bea1ab97b0d923a8ae5ce25e6eb7728941a9d1 Mon Sep 17 00:00:00 2001 From: Gabriel Rivero Date: Tue, 6 Sep 2022 12:09:00 -0400 Subject: [PATCH 30/35] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66ee8d89..fb33794d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ ## Changelog +### Version 6.0.0-alpha3 +- Upgrade ExoPlayer to 2.18.1 [#2846](https://github.com/react-native-video/react-native-video/pull/2846) ### Version 6.0.0-alpha2 From 40e8d9474fc20cc2aedd54ebac07c81b92b76f45 Mon Sep 17 00:00:00 2001 From: wood1986 <5212215+wood1986@users.noreply.github.com> Date: Wed, 7 Sep 2022 14:45:55 -0700 Subject: [PATCH 31/35] fix: add the missing dependency --- android/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/android/build.gradle b/android/build.gradle index a93e7599..90bccb8c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -41,6 +41,7 @@ dependencies { implementation "androidx.annotation:annotation:1.1.0" implementation "androidx.core:core:1.1.0" implementation "androidx.media:media:1.1.0" + implementation 'androidx.activity:activity:1.4.0' implementation('com.google.android.exoplayer:extension-okhttp:2.17.1') { exclude group: 'com.squareup.okhttp3', module: 'okhttp' From 5203fa63d49c6c503b4e4dac4a97ec1241b75ea2 Mon Sep 17 00:00:00 2001 From: wood1986 <5212215+wood1986@users.noreply.github.com> Date: Thu, 8 Sep 2022 00:31:47 -0700 Subject: [PATCH 32/35] fix: handle the initial fullscreen props --- .../com/brentvatne/exoplayer/ReactExoplayerView.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index d1a7d80c..297a230f 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -1770,6 +1770,16 @@ class ReactExoplayerView extends FrameLayout implements if (activity == null) { return; } + + if (fullScreenPlayerView == null) { + fullScreenPlayerView = new FullScreenPlayerView(getContext(), exoPlayerView, playerControlView, new OnBackPressedCallback(true) { + @Override + public void handleOnBackPressed() { + setFullscreen(false); + } + }); + } + Window window = activity.getWindow(); View decorView = window.getDecorView(); int uiOptions; From e0dc0da8c5d96ed5bfa2d6dfba6292c023f2fcbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stipe=20Perkovi=C4=87?= Date: Thu, 8 Sep 2022 13:00:21 +0200 Subject: [PATCH 33/35] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7196459..ab847de2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Fixed crash when iOS seek method called reject on the promise [#2743](https://github.com/react-native-video/react-native-video/pull/2743) - Fix maxBitRate property being ignored on Android [#2670](https://github.com/react-native-video/react-native-video/pull/2670) - Fix crash when the source is a cameraroll [#2639] (https://github.com/react-native-video/react-native-video/pull/2639) +- Fix IOS UI frame drop on loading video [#2848] (https://github.com/react-native-video/react-native-video/pull/2848) ### Version 6.0.0-alpha.1 From f0c40f939200a1099c58ece3ec8c3dca63e41173 Mon Sep 17 00:00:00 2001 From: wood1986 <5212215+wood1986@users.noreply.github.com> Date: Sat, 10 Sep 2022 11:52:46 -0700 Subject: [PATCH 34/35] fix: fix the default behaviour --- .../exoplayer/ReactExoplayerView.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 3afe48f3..7e087bb8 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -1796,15 +1796,24 @@ class ReactExoplayerView extends FrameLayout implements | SYSTEM_UI_FLAG_FULLSCREEN; } eventEmitter.fullscreenWillPresent(); - fullScreenPlayerView.show(); - eventEmitter.fullscreenDidPresent(); + post(() -> { + decorView.setSystemUiVisibility(uiOptions); + if (controls) { + fullScreenPlayerView.show(); + } + eventEmitter.fullscreenDidPresent(); + }); } else { uiOptions = View.SYSTEM_UI_FLAG_VISIBLE; eventEmitter.fullscreenWillDismiss(); - fullScreenPlayerView.dismiss(); - eventEmitter.fullscreenDidDismiss(); + post(() -> { + decorView.setSystemUiVisibility(uiOptions); + if (controls) { + fullScreenPlayerView.dismiss(); + } + eventEmitter.fullscreenDidDismiss(); + }); } - post(() -> decorView.setSystemUiVisibility(uiOptions)); } public void setUseTextureView(boolean useTextureView) { From 5b2a4741dd124009c9a3c136943698b966539b8d Mon Sep 17 00:00:00 2001 From: wood1986 <5212215+wood1986@users.noreply.github.com> Date: Sat, 10 Sep 2022 15:08:15 -0700 Subject: [PATCH 35/35] fix: add relayout when fullscreenview dismiss --- .../main/java/com/brentvatne/exoplayer/ReactExoplayerView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 7e087bb8..3e785806 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -1810,6 +1810,7 @@ class ReactExoplayerView extends FrameLayout implements decorView.setSystemUiVisibility(uiOptions); if (controls) { fullScreenPlayerView.dismiss(); + reLayout(exoPlayerView); } eventEmitter.fullscreenDidDismiss(); });