Rabbit-R1/original r1/java/sources/androidx/media3/exoplayer/video/VideoFrameReleaseHelper.java
2024-05-21 17:08:36 -04:00

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;
}
}
}
}
}