mirror of
https://github.com/Pinball3D/Rabbit-R1.git
synced 2024-12-30 11:02:31 -06:00
448 lines
17 KiB
Java
448 lines
17 KiB
Java
package androidx.media3.exoplayer.video;
|
|
|
|
import android.content.Context;
|
|
import android.hardware.display.DisplayManager;
|
|
import android.os.Handler;
|
|
import android.os.HandlerThread;
|
|
import android.os.Message;
|
|
import android.view.Choreographer;
|
|
import android.view.Display;
|
|
import android.view.Surface;
|
|
import android.view.WindowManager;
|
|
import androidx.media3.common.util.Assertions;
|
|
import androidx.media3.common.util.Log;
|
|
import androidx.media3.common.util.Util;
|
|
|
|
/* loaded from: classes2.dex */
|
|
public final class VideoFrameReleaseHelper {
|
|
private static final long MAX_ALLOWED_ADJUSTMENT_NS = 20000000;
|
|
private static final int MINIMUM_FRAMES_WITHOUT_SYNC_TO_CLEAR_SURFACE_FRAME_RATE = 30;
|
|
private static final long MINIMUM_MATCHING_FRAME_DURATION_FOR_HIGH_CONFIDENCE_NS = 5000000000L;
|
|
private static final float MINIMUM_MEDIA_FRAME_RATE_CHANGE_FOR_UPDATE_HIGH_CONFIDENCE = 0.02f;
|
|
private static final float MINIMUM_MEDIA_FRAME_RATE_CHANGE_FOR_UPDATE_LOW_CONFIDENCE = 1.0f;
|
|
private static final String TAG = "VideoFrameReleaseHelper";
|
|
private static final long VSYNC_OFFSET_PERCENTAGE = 80;
|
|
private static final long VSYNC_SAMPLE_UPDATE_PERIOD_MS = 500;
|
|
private int changeFrameRateStrategy;
|
|
private final DisplayHelper displayHelper;
|
|
private float formatFrameRate;
|
|
private long frameIndex;
|
|
private final FixedFrameRateEstimator frameRateEstimator = new FixedFrameRateEstimator();
|
|
private long lastAdjustedFrameIndex;
|
|
private long lastAdjustedReleaseTimeNs;
|
|
private long pendingLastAdjustedFrameIndex;
|
|
private long pendingLastAdjustedReleaseTimeNs;
|
|
private float playbackSpeed;
|
|
private boolean started;
|
|
private Surface surface;
|
|
private float surfaceMediaFrameRate;
|
|
private float surfacePlaybackFrameRate;
|
|
private long vsyncDurationNs;
|
|
private long vsyncOffsetNs;
|
|
private final VSyncSampler vsyncSampler;
|
|
|
|
/* JADX INFO: Access modifiers changed from: private */
|
|
/* loaded from: classes2.dex */
|
|
public interface DisplayHelper {
|
|
|
|
/* loaded from: classes2.dex */
|
|
public interface Listener {
|
|
void onDefaultDisplayChanged(Display display);
|
|
}
|
|
|
|
void register(Listener listener);
|
|
|
|
void unregister();
|
|
}
|
|
|
|
private void resetAdjustment() {
|
|
this.frameIndex = 0L;
|
|
this.lastAdjustedFrameIndex = -1L;
|
|
this.pendingLastAdjustedFrameIndex = -1L;
|
|
}
|
|
|
|
public VideoFrameReleaseHelper(Context context) {
|
|
DisplayHelper maybeBuildDisplayHelper = maybeBuildDisplayHelper(context);
|
|
this.displayHelper = maybeBuildDisplayHelper;
|
|
this.vsyncSampler = maybeBuildDisplayHelper != null ? VSyncSampler.getInstance() : null;
|
|
this.vsyncDurationNs = -9223372036854775807L;
|
|
this.vsyncOffsetNs = -9223372036854775807L;
|
|
this.formatFrameRate = -1.0f;
|
|
this.playbackSpeed = 1.0f;
|
|
this.changeFrameRateStrategy = 0;
|
|
}
|
|
|
|
public void setChangeFrameRateStrategy(int i) {
|
|
if (this.changeFrameRateStrategy == i) {
|
|
return;
|
|
}
|
|
this.changeFrameRateStrategy = i;
|
|
updateSurfacePlaybackFrameRate(true);
|
|
}
|
|
|
|
public void onStarted() {
|
|
this.started = true;
|
|
resetAdjustment();
|
|
if (this.displayHelper != null) {
|
|
((VSyncSampler) Assertions.checkNotNull(this.vsyncSampler)).addObserver();
|
|
this.displayHelper.register(new DisplayHelper.Listener() { // from class: androidx.media3.exoplayer.video.VideoFrameReleaseHelper$$ExternalSyntheticLambda0
|
|
@Override // androidx.media3.exoplayer.video.VideoFrameReleaseHelper.DisplayHelper.Listener
|
|
public final void onDefaultDisplayChanged(Display display) {
|
|
VideoFrameReleaseHelper.this.updateDefaultDisplayRefreshRateParams(display);
|
|
}
|
|
});
|
|
}
|
|
updateSurfacePlaybackFrameRate(false);
|
|
}
|
|
|
|
public void onSurfaceChanged(Surface surface) {
|
|
if (surface instanceof PlaceholderSurface) {
|
|
surface = null;
|
|
}
|
|
if (this.surface == surface) {
|
|
return;
|
|
}
|
|
clearSurfaceFrameRate();
|
|
this.surface = surface;
|
|
updateSurfacePlaybackFrameRate(true);
|
|
}
|
|
|
|
public void onPositionReset() {
|
|
resetAdjustment();
|
|
}
|
|
|
|
public void onPlaybackSpeed(float f) {
|
|
this.playbackSpeed = f;
|
|
resetAdjustment();
|
|
updateSurfacePlaybackFrameRate(false);
|
|
}
|
|
|
|
public void onFormatChanged(float f) {
|
|
this.formatFrameRate = f;
|
|
this.frameRateEstimator.reset();
|
|
updateSurfaceMediaFrameRate();
|
|
}
|
|
|
|
public void onNextFrame(long j) {
|
|
long j2 = this.pendingLastAdjustedFrameIndex;
|
|
if (j2 != -1) {
|
|
this.lastAdjustedFrameIndex = j2;
|
|
this.lastAdjustedReleaseTimeNs = this.pendingLastAdjustedReleaseTimeNs;
|
|
}
|
|
this.frameIndex++;
|
|
this.frameRateEstimator.onNextFrame(j * 1000);
|
|
updateSurfaceMediaFrameRate();
|
|
}
|
|
|
|
public void onStopped() {
|
|
this.started = false;
|
|
DisplayHelper displayHelper = this.displayHelper;
|
|
if (displayHelper != null) {
|
|
displayHelper.unregister();
|
|
((VSyncSampler) Assertions.checkNotNull(this.vsyncSampler)).removeObserver();
|
|
}
|
|
clearSurfaceFrameRate();
|
|
}
|
|
|
|
public long adjustReleaseTime(long j) {
|
|
long j2;
|
|
VSyncSampler vSyncSampler;
|
|
if (this.lastAdjustedFrameIndex != -1 && this.frameRateEstimator.isSynced()) {
|
|
long frameDurationNs = this.lastAdjustedReleaseTimeNs + (((float) (this.frameRateEstimator.getFrameDurationNs() * (this.frameIndex - this.lastAdjustedFrameIndex))) / this.playbackSpeed);
|
|
if (adjustmentAllowed(j, frameDurationNs)) {
|
|
j2 = frameDurationNs;
|
|
this.pendingLastAdjustedFrameIndex = this.frameIndex;
|
|
this.pendingLastAdjustedReleaseTimeNs = j2;
|
|
vSyncSampler = this.vsyncSampler;
|
|
if (vSyncSampler != null || this.vsyncDurationNs == -9223372036854775807L) {
|
|
return j2;
|
|
}
|
|
long j3 = vSyncSampler.sampledVsyncTimeNs;
|
|
return j3 == -9223372036854775807L ? j2 : closestVsync(j2, j3, this.vsyncDurationNs) - this.vsyncOffsetNs;
|
|
}
|
|
resetAdjustment();
|
|
}
|
|
j2 = j;
|
|
this.pendingLastAdjustedFrameIndex = this.frameIndex;
|
|
this.pendingLastAdjustedReleaseTimeNs = j2;
|
|
vSyncSampler = this.vsyncSampler;
|
|
if (vSyncSampler != null) {
|
|
}
|
|
return j2;
|
|
}
|
|
|
|
private static boolean adjustmentAllowed(long j, long j2) {
|
|
return Math.abs(j - j2) <= MAX_ALLOWED_ADJUSTMENT_NS;
|
|
}
|
|
|
|
private void updateSurfaceMediaFrameRate() {
|
|
if (Util.SDK_INT < 30 || this.surface == null) {
|
|
return;
|
|
}
|
|
float frameRate = this.frameRateEstimator.isSynced() ? this.frameRateEstimator.getFrameRate() : this.formatFrameRate;
|
|
float f = this.surfaceMediaFrameRate;
|
|
if (frameRate == f) {
|
|
return;
|
|
}
|
|
if (frameRate != -1.0f && f != -1.0f) {
|
|
if (Math.abs(frameRate - this.surfaceMediaFrameRate) < ((!this.frameRateEstimator.isSynced() || this.frameRateEstimator.getMatchingFrameDurationSumNs() < MINIMUM_MATCHING_FRAME_DURATION_FOR_HIGH_CONFIDENCE_NS) ? 1.0f : MINIMUM_MEDIA_FRAME_RATE_CHANGE_FOR_UPDATE_HIGH_CONFIDENCE)) {
|
|
return;
|
|
}
|
|
} else if (frameRate == -1.0f && this.frameRateEstimator.getFramesWithoutSyncCount() < 30) {
|
|
return;
|
|
}
|
|
this.surfaceMediaFrameRate = frameRate;
|
|
updateSurfacePlaybackFrameRate(false);
|
|
}
|
|
|
|
private void updateSurfacePlaybackFrameRate(boolean z) {
|
|
Surface surface;
|
|
float f;
|
|
if (Util.SDK_INT < 30 || (surface = this.surface) == null || this.changeFrameRateStrategy == Integer.MIN_VALUE) {
|
|
return;
|
|
}
|
|
if (this.started) {
|
|
float f2 = this.surfaceMediaFrameRate;
|
|
if (f2 != -1.0f) {
|
|
f = f2 * this.playbackSpeed;
|
|
if (z && this.surfacePlaybackFrameRate == f) {
|
|
return;
|
|
}
|
|
this.surfacePlaybackFrameRate = f;
|
|
Api30.setSurfaceFrameRate(surface, f);
|
|
}
|
|
}
|
|
f = 0.0f;
|
|
if (z) {
|
|
}
|
|
this.surfacePlaybackFrameRate = f;
|
|
Api30.setSurfaceFrameRate(surface, f);
|
|
}
|
|
|
|
private void clearSurfaceFrameRate() {
|
|
Surface surface;
|
|
if (Util.SDK_INT < 30 || (surface = this.surface) == null || this.changeFrameRateStrategy == Integer.MIN_VALUE || this.surfacePlaybackFrameRate == 0.0f) {
|
|
return;
|
|
}
|
|
this.surfacePlaybackFrameRate = 0.0f;
|
|
Api30.setSurfaceFrameRate(surface, 0.0f);
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: private */
|
|
public void updateDefaultDisplayRefreshRateParams(Display display) {
|
|
if (display != null) {
|
|
long refreshRate = (long) (1.0E9d / display.getRefreshRate());
|
|
this.vsyncDurationNs = refreshRate;
|
|
this.vsyncOffsetNs = (refreshRate * VSYNC_OFFSET_PERCENTAGE) / 100;
|
|
} else {
|
|
Log.w(TAG, "Unable to query display refresh rate");
|
|
this.vsyncDurationNs = -9223372036854775807L;
|
|
this.vsyncOffsetNs = -9223372036854775807L;
|
|
}
|
|
}
|
|
|
|
private static long closestVsync(long j, long j2, long j3) {
|
|
long j4;
|
|
long j5 = j2 + (((j - j2) / j3) * j3);
|
|
if (j <= j5) {
|
|
j4 = j5 - j3;
|
|
} else {
|
|
j5 = j3 + j5;
|
|
j4 = j5;
|
|
}
|
|
return j5 - j < j - j4 ? j5 : j4;
|
|
}
|
|
|
|
private static DisplayHelper maybeBuildDisplayHelper(Context context) {
|
|
if (context == null) {
|
|
return null;
|
|
}
|
|
Context applicationContext = context.getApplicationContext();
|
|
DisplayHelper maybeBuildNewInstance = Util.SDK_INT >= 17 ? DisplayHelperV17.maybeBuildNewInstance(applicationContext) : null;
|
|
return maybeBuildNewInstance == null ? DisplayHelperV16.maybeBuildNewInstance(applicationContext) : maybeBuildNewInstance;
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: private */
|
|
/* loaded from: classes2.dex */
|
|
public static final class Api30 {
|
|
private Api30() {
|
|
}
|
|
|
|
public static void setSurfaceFrameRate(Surface surface, float f) {
|
|
try {
|
|
surface.setFrameRate(f, f == 0.0f ? 0 : 1);
|
|
} catch (IllegalStateException e) {
|
|
Log.e(VideoFrameReleaseHelper.TAG, "Failed to call Surface.setFrameRate", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: private */
|
|
/* loaded from: classes2.dex */
|
|
public static final class DisplayHelperV16 implements DisplayHelper {
|
|
private final WindowManager windowManager;
|
|
|
|
@Override // androidx.media3.exoplayer.video.VideoFrameReleaseHelper.DisplayHelper
|
|
public void unregister() {
|
|
}
|
|
|
|
public static DisplayHelper maybeBuildNewInstance(Context context) {
|
|
WindowManager windowManager = (WindowManager) context.getSystemService("window");
|
|
if (windowManager != null) {
|
|
return new DisplayHelperV16(windowManager);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private DisplayHelperV16(WindowManager windowManager) {
|
|
this.windowManager = windowManager;
|
|
}
|
|
|
|
@Override // androidx.media3.exoplayer.video.VideoFrameReleaseHelper.DisplayHelper
|
|
public void register(DisplayHelper.Listener listener) {
|
|
listener.onDefaultDisplayChanged(this.windowManager.getDefaultDisplay());
|
|
}
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: private */
|
|
/* loaded from: classes2.dex */
|
|
public static final class DisplayHelperV17 implements DisplayHelper, DisplayManager.DisplayListener {
|
|
private final DisplayManager displayManager;
|
|
private DisplayHelper.Listener listener;
|
|
|
|
@Override // android.hardware.display.DisplayManager.DisplayListener
|
|
public void onDisplayAdded(int i) {
|
|
}
|
|
|
|
@Override // android.hardware.display.DisplayManager.DisplayListener
|
|
public void onDisplayRemoved(int i) {
|
|
}
|
|
|
|
public static DisplayHelper maybeBuildNewInstance(Context context) {
|
|
DisplayManager displayManager = (DisplayManager) context.getSystemService("display");
|
|
if (displayManager != null) {
|
|
return new DisplayHelperV17(displayManager);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private DisplayHelperV17(DisplayManager displayManager) {
|
|
this.displayManager = displayManager;
|
|
}
|
|
|
|
@Override // androidx.media3.exoplayer.video.VideoFrameReleaseHelper.DisplayHelper
|
|
public void register(DisplayHelper.Listener listener) {
|
|
this.listener = listener;
|
|
this.displayManager.registerDisplayListener(this, Util.createHandlerForCurrentLooper());
|
|
listener.onDefaultDisplayChanged(getDefaultDisplay());
|
|
}
|
|
|
|
@Override // androidx.media3.exoplayer.video.VideoFrameReleaseHelper.DisplayHelper
|
|
public void unregister() {
|
|
this.displayManager.unregisterDisplayListener(this);
|
|
this.listener = null;
|
|
}
|
|
|
|
@Override // android.hardware.display.DisplayManager.DisplayListener
|
|
public void onDisplayChanged(int i) {
|
|
DisplayHelper.Listener listener = this.listener;
|
|
if (listener == null || i != 0) {
|
|
return;
|
|
}
|
|
listener.onDefaultDisplayChanged(getDefaultDisplay());
|
|
}
|
|
|
|
private Display getDefaultDisplay() {
|
|
return this.displayManager.getDisplay(0);
|
|
}
|
|
}
|
|
|
|
/* loaded from: classes2.dex */
|
|
private static final class VSyncSampler implements Choreographer.FrameCallback, Handler.Callback {
|
|
private static final int CREATE_CHOREOGRAPHER = 0;
|
|
private static final VSyncSampler INSTANCE = new VSyncSampler();
|
|
private static final int MSG_ADD_OBSERVER = 1;
|
|
private static final int MSG_REMOVE_OBSERVER = 2;
|
|
private Choreographer choreographer;
|
|
private final HandlerThread choreographerOwnerThread;
|
|
private final Handler handler;
|
|
private int observerCount;
|
|
public volatile long sampledVsyncTimeNs = -9223372036854775807L;
|
|
|
|
public static VSyncSampler getInstance() {
|
|
return INSTANCE;
|
|
}
|
|
|
|
private VSyncSampler() {
|
|
HandlerThread handlerThread = new HandlerThread("ExoPlayer:FrameReleaseChoreographer");
|
|
this.choreographerOwnerThread = handlerThread;
|
|
handlerThread.start();
|
|
Handler createHandler = Util.createHandler(handlerThread.getLooper(), this);
|
|
this.handler = createHandler;
|
|
createHandler.sendEmptyMessage(0);
|
|
}
|
|
|
|
public void addObserver() {
|
|
this.handler.sendEmptyMessage(1);
|
|
}
|
|
|
|
public void removeObserver() {
|
|
this.handler.sendEmptyMessage(2);
|
|
}
|
|
|
|
@Override // android.view.Choreographer.FrameCallback
|
|
public void doFrame(long j) {
|
|
this.sampledVsyncTimeNs = j;
|
|
((Choreographer) Assertions.checkNotNull(this.choreographer)).postFrameCallbackDelayed(this, 500L);
|
|
}
|
|
|
|
@Override // android.os.Handler.Callback
|
|
public boolean handleMessage(Message message) {
|
|
int i = message.what;
|
|
if (i == 0) {
|
|
createChoreographerInstanceInternal();
|
|
return true;
|
|
}
|
|
if (i == 1) {
|
|
addObserverInternal();
|
|
return true;
|
|
}
|
|
if (i != 2) {
|
|
return false;
|
|
}
|
|
removeObserverInternal();
|
|
return true;
|
|
}
|
|
|
|
private void createChoreographerInstanceInternal() {
|
|
try {
|
|
this.choreographer = Choreographer.getInstance();
|
|
} catch (RuntimeException e) {
|
|
Log.w(VideoFrameReleaseHelper.TAG, "Vsync sampling disabled due to platform error", e);
|
|
}
|
|
}
|
|
|
|
private void addObserverInternal() {
|
|
Choreographer choreographer = this.choreographer;
|
|
if (choreographer != null) {
|
|
int i = this.observerCount + 1;
|
|
this.observerCount = i;
|
|
if (i == 1) {
|
|
choreographer.postFrameCallback(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void removeObserverInternal() {
|
|
Choreographer choreographer = this.choreographer;
|
|
if (choreographer != null) {
|
|
int i = this.observerCount - 1;
|
|
this.observerCount = i;
|
|
if (i == 0) {
|
|
choreographer.removeFrameCallback(this);
|
|
this.sampledVsyncTimeNs = -9223372036854775807L;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|