Skip to content

Commit

Permalink
Merge branch 'master' into feat/moveViewTypeAndDrmInSource
Browse files Browse the repository at this point in the history
  • Loading branch information
freeboub authored Jun 6, 2024
2 parents 784c2ae + 8693dbc commit 0291a09
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 31 deletions.
21 changes: 21 additions & 0 deletions .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ body:

- type: dropdown
id: platforms
validations:
required: true
attributes:
label: What platforms are you having the problem on?
multiple: true
Expand All @@ -28,6 +30,25 @@ body:
- visionOS
- Android TV
- Apple tvOS

- type: input
id: system_version
attributes:
label: System Version
description: What version of the system is using device that you are experiencing the issue?
validations:
required: true

- type: dropdown
id: device
validations:
required: true
attributes:
label: On what device are you experiencing the issue?
multiple: true
options:
- Real device
- Simulator

- type: dropdown
id: architecture
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,29 +256,37 @@ public class ReactExoplayerView extends FrameLayout implements
private long lastBufferDuration = -1;
private long lastDuration = -1;

private boolean viewHasDropped = false;
private void updateProgress() {
if (player != null) {
if (playerControlView != null && isPlayingAd() && controls) {
playerControlView.hide();
}
long bufferedDuration = player.getBufferedPercentage() * player.getDuration() / 100;
long duration = player.getDuration();
long pos = player.getCurrentPosition();
if (pos > duration) {
pos = duration;
}

if (lastPos != pos
|| lastBufferDuration != bufferedDuration
|| lastDuration != duration) {
lastPos = pos;
lastBufferDuration = bufferedDuration;
lastDuration = duration;
eventEmitter.progressChanged(pos, bufferedDuration, player.getDuration(), getPositionInFirstPeriodMsForCurrentWindow(pos));
}
}
}

private final Handler progressHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
if (msg.what == SHOW_PROGRESS) {
if (player != null) {
if (playerControlView != null && isPlayingAd() && controls) {
playerControlView.hide();
}
long pos = player.getCurrentPosition();
long bufferedDuration = player.getBufferedPercentage() * player.getDuration() / 100;
long duration = player.getDuration();

if (lastPos != pos
|| lastBufferDuration != bufferedDuration
|| lastDuration != duration) {
lastPos = pos;
lastBufferDuration = bufferedDuration;
lastDuration = duration;
eventEmitter.progressChanged(pos, bufferedDuration, player.getDuration(), getPositionInFirstPeriodMsForCurrentWindow(pos));
}
msg = obtainMessage(SHOW_PROGRESS);
sendMessageDelayed(msg, Math.round(mProgressUpdateInterval));
}
updateProgress();
msg = obtainMessage(SHOW_PROGRESS);
sendMessageDelayed(msg, Math.round(mProgressUpdateInterval));
}
}
};
Expand Down Expand Up @@ -363,6 +371,8 @@ protected void onDetachedFromWindow() {
public void cleanUpResources() {
stopPlayback();
themedReactContext.removeLifecycleEventListener(this);
releasePlayer();
viewHasDropped = true;
}

//BandwidthMeter.EventListener implementation
Expand Down Expand Up @@ -635,6 +645,9 @@ private void initializePlayer() {
Activity activity = themedReactContext.getCurrentActivity();
// This ensures all props have been settled, to avoid async racing conditions.
mainRunnable = () -> {
if (viewHasDropped) {
return;
}
try {
if (player == null) {
exoPlayerView.updateSurfaceView(source.getViewType());
Expand All @@ -646,6 +659,10 @@ private void initializePlayer() {
// DRM session manager creation must be done on a different thread to prevent crashes so we start a new thread
ExecutorService es = Executors.newSingleThreadExecutor();
es.execute(() -> {
// DRM initialization must run on a different thread
if (viewHasDropped) {
return;
}
if (activity == null) {
DebugLog.e(TAG, "Failed to initialize Player!, null activity");
eventEmitter.error("Failed to initialize Player!", new Exception("Current Activity is null!"), "1001");
Expand All @@ -654,12 +671,15 @@ private void initializePlayer() {

// Initialize handler to run on the main thread
activity.runOnUiThread(() -> {
if (viewHasDropped) {
return;
}
try {
// Source initialization must run on the main thread
initializePlayerSource();
} catch (Exception ex) {
self.playerNeedsSource = true;
DebugLog.e(TAG, "Failed to initialize Player!");
DebugLog.e(TAG, "Failed to initialize Player! 1");
DebugLog.e(TAG, ex.toString());
ex.printStackTrace();
self.eventEmitter.error(ex.toString(), ex, "1001");
Expand All @@ -671,7 +691,7 @@ private void initializePlayer() {
}
} catch (Exception ex) {
self.playerNeedsSource = true;
DebugLog.e(TAG, "Failed to initialize Player!");
DebugLog.e(TAG, "Failed to initialize Player! 2");
DebugLog.e(TAG, ex.toString());
ex.printStackTrace();
eventEmitter.error(ex.toString(), ex, "1001");
Expand Down Expand Up @@ -1352,6 +1372,7 @@ public void onEvents(@NonNull Player player, Player.Events events) {
break;
case Player.STATE_ENDED:
text += "ended";
updateProgress();
eventEmitter.end();
onStopPlayback();
setKeepScreenOn(false);
Expand Down Expand Up @@ -1629,6 +1650,7 @@ public void onPositionDiscontinuity(@NonNull Player.PositionInfo oldPosition, @N
// so we need to explicitly detect it.
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION
&& player.getRepeatMode() == Player.REPEAT_MODE_ONE) {
updateProgress();
eventEmitter.end();
}
}
Expand Down
4 changes: 2 additions & 2 deletions ios/Video/NowPlayingInfoCenterManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ class NowPlayingInfoCenterManager {
return
}

if let observer = observers[players.hashValue] {
if let observer = observers[player.hashValue] {
observer.invalidate()
}

observers.removeValue(forKey: players.hashValue)
observers.removeValue(forKey: player.hashValue)
players.remove(player)

if currentPlayer == player {
Expand Down
27 changes: 19 additions & 8 deletions ios/Video/RCTVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH

// MARK: - Progress

func sendProgressUpdate() {
func sendProgressUpdate(didEnd: Bool = false) {
#if !USE_GOOGLE_IMA
// If we dont use Ads and onVideoProgress is not defined we dont need to run this code
guard onVideoProgress != nil else { return }
Expand All @@ -330,11 +330,11 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
}
let currentPlaybackTime = _player?.currentItem?.currentDate()
let duration = CMTimeGetSeconds(playerDuration)
let currentTimeSecs = CMTimeGetSeconds(currentTime ?? .zero)
var currentTimeSecs = CMTimeGetSeconds(currentTime ?? .zero)

NotificationCenter.default.post(name: NSNotification.Name("RCTVideo_progress"), object: nil, userInfo: [
"progress": NSNumber(value: currentTimeSecs / duration),
])
if currentTimeSecs > duration || didEnd {
currentTimeSecs = duration
}

if currentTimeSecs >= 0 {
#if USE_GOOGLE_IMA
Expand All @@ -344,10 +344,10 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
}
#endif
onVideoProgress?([
"currentTime": NSNumber(value: Float(currentTimeSecs)),
"currentTime": currentTimeSecs,
"playableDuration": RCTVideoUtils.calculatePlayableDuration(_player, withSource: _source),
"atValue": NSNumber(value: currentTime?.value ?? .zero),
"currentPlaybackTime": NSNumber(value: NSNumber(value: Double(currentPlaybackTime?.timeIntervalSince1970 ?? 0 * 1000)).int64Value),
"atValue": currentTime?.value ?? .zero,
"currentPlaybackTime": NSNumber(value: Double(currentPlaybackTime?.timeIntervalSince1970 ?? 0 * 1000)).int64Value,
"target": reactTag,
"seekableDuration": RCTVideoUtils.calculateSeekableDuration(_player),
])
Expand Down Expand Up @@ -1232,17 +1232,27 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
// MARK: - Lifecycle

override func removeFromSuperview() {
self._player?.replaceCurrentItem(with: nil)
if let player = _player {
player.pause()
NowPlayingInfoCenterManager.shared.removePlayer(player: player)
}
_playerItem = nil
_source = nil
_chapters = nil
_drm = nil
_textTracks = nil
_selectedTextTrackCriteria = nil
_selectedAudioTrackCriteria = nil
_presentingViewController = nil

_player = nil
_resouceLoaderDelegate = nil
_playerObserver.clearPlayer()

#if USE_GOOGLE_IMA
_imaAdsManager.releaseAds()
_imaAdsManager = nil
#endif

self.removePlayerLayer()
Expand Down Expand Up @@ -1561,6 +1571,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH

@objc
func handlePlayerItemDidReachEnd(notification: NSNotification!) {
sendProgressUpdate(didEnd: true)
onVideoEnd?(["target": reactTag as Any])
#if USE_GOOGLE_IMA
if notification.object as? AVPlayerItem == _player?.currentItem {
Expand Down

0 comments on commit 0291a09

Please sign in to comment.