Merge branch 'master' into fix-memleak

This commit is contained in:
Olivier Bouillet 2023-08-03 20:53:12 +02:00 committed by GitHub
commit 236d17e8b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 80 additions and 72 deletions

View File

@ -10,37 +10,24 @@ assignees: ''
# Bug
<!--
Before opening a ticket
* Ensure the issue has not been already reported
* Please test using the latest release of the library, as maybe said bug has been already fixed.
* Provide a clear and concise description of what the bug is.
* If the library has multiple install methods, describe installation method (e.g., pod, not pod, with jetifier etc)
* Include screenshots if needed.
Very important, before opening a ticket:
1) Ensure the issue has not been already reported
2) lease test using the latest release (including 6.0.0 preRelease) of the library, as maybe the bug has been already fixed.
3) please don't use emulator to reproduce issues. if you have strange or sporadic error check if this is not devices specific (understand that this library is just a binding to player).
4) ensure you cannot solve the issue by yourself using following guide: https://github.com/react-native-video/react-native-video/blob/master/docs/DEBUGGING.md
-->
## Platform
<!--
Platform where your bug is happening.
-->
Which player are you experiencing the problem on:
* iOS
* Android
* Windows UWP
* Windows WPF
* Windows
## Environment info
<!--
Run `react-native info` in your terminal and copy the results here. Also, include the *precise* version number of this library that you are using in the project
-->
React native info output:
```bash
// paste it here
```
<!-- This fields are mandatory -->
Library version: x.x.x
Device:
## Steps To Reproduce

View File

@ -2,6 +2,7 @@
### Version 6.0.0-alpha.7
- Android: Fix memory leaks from AudioManager [#3123](https://github.com/react-native-video/react-native-video/pull/3123)
- Android: Fixed syntax error [#3182](https://github.com/react-native-video/react-native-video/issues/3182)
### Version 6.0.0-alpha.6
- Feature: Video range support [#3030](https://github.com/react-native-video/react-native-video/pull/3030)

View File

@ -77,7 +77,7 @@ export default class Video extends Component {
this.setNativeProps({ fullscreen: false });
};
save = async (options?) => {
save = async (options) => {
return await NativeModules.VideoManager.save(options, findNodeHandle(this._root));
}
@ -416,13 +416,6 @@ Video.propTypes = {
FilterType.SEPIA,
]),
filterEnabled: PropTypes.bool,
/* Native only */
src: PropTypes.object,
seek: PropTypes.oneOfType([
PropTypes.number,
PropTypes.object,
]),
fullscreen: PropTypes.bool,
onVideoLoadStart: PropTypes.func,
onVideoLoad: PropTypes.func,
onVideoBuffer: PropTypes.func,
@ -566,10 +559,4 @@ Video.propTypes = {
...ViewPropTypes,
};
const RCTVideo = requireNativeComponent('RCTVideo', Video, {
nativeOnly: {
src: true,
seek: true,
fullscreen: true,
},
});
const RCTVideo = requireNativeComponent('RCTVideo');

View File

@ -17,6 +17,7 @@ def configStringPath = (
).md5()
android {
namespace 'com.brentvatne.react'
compileSdkVersion safeExtGet('compileSdkVersion', 31)
buildToolsVersion safeExtGet('buildToolsVersion', '30.0.2')

View File

@ -14,27 +14,27 @@
android:paddingTop="4dp"
android:orientation="horizontal">
<ImageButton android:id="@id/exo_prev"
<ImageButton android:id="@+id/exo_prev"
style="@style/ExoMediaButton.Previous"/>
<ImageButton android:id="@id/exo_rew"
<ImageButton android:id="@+id/exo_rew"
style="@style/ExoMediaButton.Rewind"/>
<FrameLayout
android:id="@+id/exo_play_pause_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<ImageButton android:id="@id/exo_play"
<ImageButton android:id="@+id/exo_play"
style="@style/ExoMediaButton.Play"/>
<ImageButton android:id="@id/exo_pause"
<ImageButton android:id="@+id/exo_pause"
style="@style/ExoMediaButton.Pause"/>
</FrameLayout>
<ImageButton android:id="@id/exo_ffwd"
<ImageButton android:id="@+id/exo_ffwd"
style="@style/ExoMediaButton.FastForward"/>
<ImageButton android:id="@id/exo_next"
<ImageButton android:id="@+id/exo_next"
style="@style/ExoMediaButton.Next"/>
</LinearLayout>
@ -46,7 +46,7 @@
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView android:id="@id/exo_position"
<TextView android:id="@+id/exo_position"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:textSize="14sp"
@ -57,12 +57,12 @@
android:textColor="#FFBEBEBE"/>
<com.google.android.exoplayer2.ui.DefaultTimeBar
android:id="@id/exo_progress"
android:id="@+id/exo_progress"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="26dp"/>
<TextView android:id="@id/exo_duration"
<TextView android:id="@+id/exo_duration"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:textSize="14sp"
@ -73,7 +73,7 @@
android:textColor="#FFBEBEBE"/>
<ImageButton
android:id="@id/exo_fullscreen"
android:id="@+id/exo_fullscreen"
style="@style/ExoMediaButton.FullScreen"
android:layout_width="30dp"
android:layout_height="30dp"

View File

@ -4,7 +4,7 @@ import GoogleInteractiveMediaAds
class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
private var _video:RCTVideo
private weak var _video: RCTVideo?
/* Entry point for the SDK. Used to make ad requests. */
private var adsLoader: IMAAdsLoader!
@ -23,6 +23,7 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
}
func requestAds() {
guard let _video = _video else {return}
// Create ad display container for ad rendering.
let adDisplayContainer = IMAAdDisplayContainer(adContainer: _video, viewController: _video.reactViewController())
@ -54,6 +55,7 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
// MARK: - IMAAdsLoaderDelegate
func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) {
guard let _video = _video else {return}
// Grab the instance of the IMAAdsManager and set yourself as the delegate.
adsManager = adsLoadedData.adsManager
adsManager?.delegate = self
@ -71,12 +73,13 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
print("Error loading ads: " + adErrorData.adError.message!)
}
_video.setPaused(false)
_video?.setPaused(false)
}
// MARK: - IMAAdsManagerDelegate
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
guard let _video = _video else {return}
// Mute ad if the main player is muted
if (_video.isMuted()) {
adsManager.volume = 0;
@ -102,19 +105,19 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
}
// Fall back to playing content
_video.setPaused(false)
_video?.setPaused(false)
}
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {
// Pause the content for the SDK to play ads.
_video.setPaused(true)
_video.setAdPlaying(true)
_video?.setPaused(true)
_video?.setAdPlaying(true)
}
func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) {
// Resume the content since the SDK is done playing ads (at least for now).
_video.setAdPlaying(false)
_video.setPaused(false)
_video?.setAdPlaying(false)
_video?.setPaused(false)
}
// MARK: - Helpers

View File

@ -25,7 +25,7 @@ protocol RCTPlayerObserverHandler: RCTPlayerObserverHandlerObjc {
class RCTPlayerObserver: NSObject {
var _handlers: RCTPlayerObserverHandler!
weak var _handlers: RCTPlayerObserverHandler?
var player:AVPlayer? {
willSet {
@ -84,11 +84,13 @@ class RCTPlayerObserver: NSObject {
private var _playerViewControllerOverlayFrameObserver:NSKeyValueObservation?
deinit {
if let _handlers = _handlers {
NotificationCenter.default.removeObserver(_handlers)
}
}
func addPlayerObservers() {
guard let player = player else {
guard let player = player, let _handlers = _handlers else {
return
}
@ -102,7 +104,7 @@ class RCTPlayerObserver: NSObject {
}
func addPlayerItemObservers() {
guard let playerItem = playerItem else { return }
guard let playerItem = playerItem, let _handlers = _handlers else { return }
_playerItemStatusObserver = playerItem.observe(\.status, options: [.new, .old], changeHandler: _handlers.handlePlayerItemStatusChange)
_playerPlaybackBufferEmptyObserver = playerItem.observe(\.isPlaybackBufferEmpty, options: [.new, .old], changeHandler: _handlers.handlePlaybackBufferKeyEmpty)
@ -118,7 +120,7 @@ class RCTPlayerObserver: NSObject {
}
func addPlayerViewControllerObservers() {
guard let playerViewController = playerViewController else { return }
guard let playerViewController = playerViewController, let _handlers = _handlers else { return }
_playerViewControllerReadyForDisplayObserver = playerViewController.observe(\.isReadyForDisplay, options: [.new], changeHandler: _handlers.handleReadyForDisplay)
@ -131,6 +133,7 @@ class RCTPlayerObserver: NSObject {
}
func addPlayerLayerObserver() {
guard let _handlers = _handlers else {return}
_playerLayerReadyForDisplayObserver = playerLayer?.observe(\.isReadyForDisplay, options: [.new], changeHandler: _handlers.handleReadyForDisplay)
}
@ -139,6 +142,7 @@ class RCTPlayerObserver: NSObject {
}
func addPlayerTimeObserver() {
guard let _handlers = _handlers else {return}
removePlayerTimeObserver()
let progressUpdateIntervalMS:Float64 = _progressUpdateInterval / 1000
// @see endScrubbing in AVPlayerDemoPlaybackViewController.m
@ -174,6 +178,7 @@ class RCTPlayerObserver: NSObject {
}
func attachPlayerEventListeners() {
guard let _handlers = _handlers else {return}
NotificationCenter.default.removeObserver(_handlers,
name:NSNotification.Name.AVPlayerItemDidPlayToEndTime,
@ -202,6 +207,8 @@ class RCTPlayerObserver: NSObject {
func clearPlayer() {
player = nil
playerItem = nil
if let _handlers = _handlers {
NotificationCenter.default.removeObserver(_handlers)
}
}
}

View File

@ -1,5 +1,6 @@
#import <React/RCTViewManager.h>
#import "RCTVideoSwiftLog.h"
#import "RCTEventDispatcher.h"
#if __has_include(<react-native-video/RCTVideoCache.h>)
#import "RCTVideoCache.h"

View File

@ -59,6 +59,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
private var _fullscreenAutorotate:Bool = true
private var _fullscreenOrientation:String! = "all"
private var _fullscreenPlayerPresented:Bool = false
private var _fullscreenUncontrolPlayerPresented:Bool = false // to call events switching full screen mode from player controls
private var _filterName:String!
private var _filterEnabled:Bool = false
private var _presentingViewController:UIViewController?
@ -246,7 +247,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
// MARK: - Player and source
@objc
func setSrc(_ source:NSDictionary!) {
DispatchQueue.global(qos: .default).async {
DispatchQueue.global(qos: .default).async { [weak self] in
guard let self = self else {return}
self._source = VideoSource(source)
if (self._source?.uri == nil || self._source?.uri == "") {
self._player?.replaceCurrentItem(with: nil)
@ -662,7 +664,13 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
self.onVideoFullscreenPlayerWillPresent?(["target": reactTag as Any])
if let playerViewController = _playerViewController {
viewController.present(playerViewController, animated:true, completion:{
if(_controls) {
// prevents crash https://github.com/react-native-video/react-native-video/issues/3040
self._playerViewController?.removeFromParent()
}
viewController.present(playerViewController, animated:true, completion:{ [weak self] in
guard let self = self else {return}
self._playerViewController?.showsPlaybackControls = self._controls
self._fullscreenPlayerPresented = fullscreen
self._playerViewController?.autorotate = self._fullscreenAutorotate
@ -674,8 +682,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
}
} else if !fullscreen && _fullscreenPlayerPresented, let _playerViewController = _playerViewController {
self.videoPlayerViewControllerWillDismiss(playerViewController: _playerViewController)
_presentingViewController?.dismiss(animated: true, completion:{
self.videoPlayerViewControllerDidDismiss(playerViewController: _playerViewController)
_presentingViewController?.dismiss(animated: true, completion:{[weak self] in
self?.videoPlayerViewControllerDidDismiss(playerViewController: _playerViewController)
})
}
}
@ -1103,12 +1111,27 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
let oldRect = change.oldValue
let newRect = change.newValue
if !oldRect!.equalTo(newRect!) {
// https://github.com/react-native-video/react-native-video/issues/3085#issuecomment-1557293391
if newRect!.equalTo(UIScreen.main.bounds) {
RCTLog("in fullscreen")
if (!_fullscreenUncontrolPlayerPresented) {
_fullscreenUncontrolPlayerPresented = true;
self.onVideoFullscreenPlayerWillPresent?(["target": self.reactTag as Any])
self.onVideoFullscreenPlayerDidPresent?(["target": self.reactTag as Any])
}
} else {
NSLog("not fullscreen")
if (_fullscreenUncontrolPlayerPresented) {
_fullscreenUncontrolPlayerPresented = false;
self.onVideoFullscreenPlayerWillDismiss?(["target": self.reactTag as Any])
self.onVideoFullscreenPlayerDidDismiss?(["target": self.reactTag as Any])
}
}
self.reactViewController().view.frame = UIScreen.main.bounds
self.reactViewController().view.setNeedsLayout()
} else {NSLog("not fullscreen")}
}
}

View File

@ -2,7 +2,7 @@ import AVKit
class RCTVideoPlayerViewController: AVPlayerViewController {
var rctDelegate:RCTVideoPlayerViewControllerDelegate!
weak var rctDelegate: RCTVideoPlayerViewControllerDelegate?
// Optional paramters
var preferredOrientation:String?
@ -20,10 +20,8 @@ class RCTVideoPlayerViewController: AVPlayerViewController {
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if rctDelegate != nil {
rctDelegate.videoPlayerViewControllerWillDismiss(playerViewController: self)
rctDelegate.videoPlayerViewControllerDidDismiss(playerViewController: self)
}
rctDelegate?.videoPlayerViewControllerWillDismiss(playerViewController: self)
rctDelegate?.videoPlayerViewControllerDidDismiss(playerViewController: self)
}
#if !TARGET_OS_TV