929 lines
30 KiB
Java
929 lines
30 KiB
Java
package defpackage;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.nio.file.Path;
|
|
import java.util.List;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.ThreadFactory;
|
|
import javax.sound.sampled.LineUnavailableException;
|
|
import org.lwjgl.PointerBuffer;
|
|
import org.lwjgl.system.MemoryStack;
|
|
import org.lwjgl.util.tinyfd.TinyFileDialogs;
|
|
|
|
public final class ajn implements aji, ajk {
|
|
private static final ajn INSTANCE = new ajn();
|
|
private static final String CLIPS_DIRECTORY = "clips";
|
|
private static final String IO_THREAD = "EvoClipIO";
|
|
private static final String EXPORT_THREAD = "EvoClipExport";
|
|
private static final String NOTIFY_TITLE = "Clips";
|
|
private static final String STATUS_SAVED = "saved";
|
|
private static final String STATUS_EMPTY = "buffer is empty";
|
|
private static final String STATUS_RECORDING = "recording";
|
|
private static final String STATUS_STOPPED = "recording saved";
|
|
private static final String STATUS_EXPORTED = "exported";
|
|
private static final String STATUS_FAILED = "failed";
|
|
private static final String STATUS_BUSY = "already working";
|
|
private static final String STATUS_NO_AUDIO = "audio device unavailable";
|
|
private static final String STATUS_NO_LOOPBACK = "game audio needs a loopback device";
|
|
private static final String STATUS_CANCELLED = "export cancelled";
|
|
private static final String DIALOG_TITLE = "Save clip";
|
|
private static final String FILTER_PATTERN = "*.mp4";
|
|
private static final String FILTER_LABEL = "MP4 video";
|
|
private static final String SAVE_FAILURE = "clip save failed";
|
|
private static final String RECORD_FAILURE = "clip recording failed";
|
|
private static final String EXPORT_FAILURE = "clip export failed";
|
|
private static final String AUDIO_FAILURE = "clip audio capture unavailable for channel {}";
|
|
private static final String LABEL_RECORDING = "REC ";
|
|
private static final String LABEL_SAVING = "Saving clip";
|
|
private static final String LABEL_EXPORTING = "Exporting ";
|
|
private static final String TIME_SEPARATOR = ":";
|
|
private static final String TIME_PAD = "0";
|
|
private static final String PERCENT = "%";
|
|
private static final int PIXEL_POOL_CAPACITY = 8;
|
|
private static final int MIN_WORKERS = 1;
|
|
private static final int MAX_WORKERS = 4;
|
|
private static final int CORES_PER_WORKER = 2;
|
|
private static final int FRAMES_PER_WORKER = 30;
|
|
private static final int MAX_CATCHUP_INTERVALS = 4;
|
|
private static final long FLUSH_TIMEOUT_MILLIS = 3000L;
|
|
private static final long NANOS_PER_SECOND = 1000000000L;
|
|
private static final long MILLIS_PER_SECOND = 1000L;
|
|
private static final long SECONDS_PER_MINUTE = 60L;
|
|
private static final int PAD_LIMIT = 10;
|
|
private static final int PERCENT_SCALE = 100;
|
|
private static final int MIN_EXPORT_CHUNK = 15;
|
|
private static final float PROGRESS_COMPLETE = 1.0F;
|
|
private final akd library = new akd(new File(bz.DIRECTORY, "clips").toPath());
|
|
private final ajf pixels = new ajf((-530988065 | 530988073) + (-530988065 & 530988073));
|
|
private final akg ring = new akg(
|
|
(4068614446794629938L | -4068614446794629938L) + (4068614446794629938L & -4068614446794629938L),
|
|
(-7238148903045534534L ^ 7238148903045534534L) + ((-7238148903045534534L & 7238148903045534534L) << 1)
|
|
);
|
|
private final aju audioRing = new aju((-3540198577801529315L ^ 3540198577801529315L) + ((-3540198577801529315L & 3540198577801529315L) << 1));
|
|
private final ExecutorService io = Executors.newSingleThreadExecutor(
|
|
factory("EvoClipIO")
|
|
);
|
|
private final ExecutorService exports = Executors.newSingleThreadExecutor(
|
|
factory("EvoClipExport")
|
|
);
|
|
private final Object writerLock = new Object();
|
|
private final Object poolLock = new Object();
|
|
private volatile ajj encoders;
|
|
private ajz writer;
|
|
private volatile ajq systemAudio;
|
|
private volatile ajq microphoneAudio;
|
|
private volatile boolean systemAudioFailed;
|
|
private volatile boolean microphoneFailed;
|
|
private long lastCaptureNanos;
|
|
private int lastLevelId;
|
|
private volatile int frameWidth;
|
|
private volatile int frameHeight;
|
|
private volatile boolean recording;
|
|
private volatile boolean forcedExport;
|
|
private volatile long recordingStartedMillis;
|
|
private volatile boolean saving;
|
|
private volatile boolean exporting;
|
|
volatile float exportProgress;
|
|
|
|
private ajn() {
|
|
}
|
|
|
|
public static ajn getInstance() {
|
|
return INSTANCE;
|
|
}
|
|
|
|
public akd library() {
|
|
return this.library;
|
|
}
|
|
|
|
public int bufferedFrames() {
|
|
return this.ring.frameCount();
|
|
}
|
|
|
|
public long bufferedMillis() {
|
|
return this.ring.spanMillis();
|
|
}
|
|
|
|
public long bufferedBytes() {
|
|
return this.ring.usedBytes();
|
|
}
|
|
|
|
public boolean isRecording() {
|
|
return this.recording;
|
|
}
|
|
|
|
public Path activeClipPath() {
|
|
synchronized (this.writerLock) {
|
|
return this.writer == null ? null : this.writer.path();
|
|
}
|
|
}
|
|
|
|
public boolean isExporting() {
|
|
return this.exporting;
|
|
}
|
|
|
|
public float exportProgress() {
|
|
return this.exportProgress;
|
|
}
|
|
|
|
public ajp status() {
|
|
ajp var1 = null;
|
|
int var2 = 1695866167;
|
|
|
|
while (true) {
|
|
switch (var2) {
|
|
case -2116776308:
|
|
if (this.recording) {
|
|
var2 = -1047961509;
|
|
} else {
|
|
var2 = -1204917921;
|
|
}
|
|
break;
|
|
case -1394340563:
|
|
return var1;
|
|
case -1204917921:
|
|
if (this.saving) {
|
|
var2 = 1668494564;
|
|
} else {
|
|
var2 = 1605639620;
|
|
}
|
|
break;
|
|
case -1047961509:
|
|
return new ajp(ajo.RECORDING, "REC " + elapsed(System.currentTimeMillis() - this.recordingStartedMillis), 1.0F);
|
|
case 541660842:
|
|
return ajp.NONE;
|
|
case 1605639620:
|
|
if (this.exporting) {
|
|
var2 = 1913038014;
|
|
} else {
|
|
var2 = 541660842;
|
|
}
|
|
break;
|
|
case 1668494564:
|
|
return new ajp(ajo.SAVING, "Saving clip", 1.0F);
|
|
case 1695866167:
|
|
default:
|
|
var1 = aje.getInstance().status();
|
|
if (var1.active()) {
|
|
var2 = -1394340563;
|
|
} else {
|
|
var2 = -2116776308;
|
|
}
|
|
break;
|
|
case 1913038014:
|
|
return new ajp(ajo.EXPORTING, "Exporting " + Math.round(this.exportProgress * 100.0F) + "%", this.exportProgress);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void captureFrame() {
|
|
ti var1 = ti.INSTANCE;
|
|
boolean var2 = aje.getInstance().advance();
|
|
if ((var1.isEnabled() || this.recording) && aqg.mc.level != null && aqg.mc.player != null) {
|
|
if (var2 || var1.instantReplay.isEnabled() || this.recording) {
|
|
int var3 = System.identityHashCode(aqg.mc.level);
|
|
if (var3 != this.lastLevelId) {
|
|
this.lastLevelId = var3;
|
|
this.ring.clear();
|
|
}
|
|
|
|
long var4 = System.nanoTime();
|
|
long var6 = ((204804686408849003L ^ -204804685408849003L) + ((204804686408849003L & -204804685408849003L) << 1)) / var1.captureFps();
|
|
if (var4 - this.lastCaptureNanos >= var6) {
|
|
this.lastCaptureNanos = var4 - this.lastCaptureNanos
|
|
> var6 * ((6528836991116781498L ^ -6528836991116781494L) + ((6528836991116781498L & -6528836991116781494L) << 1))
|
|
? var4
|
|
: this.lastCaptureNanos + var6;
|
|
this.ring.resize(var1.bufferMillis(), var1.bufferBytes());
|
|
this.audioRing.resize(var1.bufferMillis());
|
|
this.startEncoders();
|
|
this.syncAudioCapture(var1);
|
|
ajl.capture(var1.captureHeight(), this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public byte[] borrow(int var1) {
|
|
return this.pixels.take(var1);
|
|
}
|
|
|
|
@Override
|
|
public boolean accept(byte[] var1, int var2, int var3, long var4) {
|
|
ajj var6 = null;
|
|
int var8 = 0;
|
|
int var7 = -1692979841;
|
|
|
|
while (true) {
|
|
switch (var7) {
|
|
case -2101731117:
|
|
var8 = 0;
|
|
var7 = 113816286;
|
|
break;
|
|
case -1692979841:
|
|
default:
|
|
var6 = this.encoders;
|
|
if (var6 != null) {
|
|
var7 = -1472899494;
|
|
} else {
|
|
var7 = -2101731117;
|
|
}
|
|
break;
|
|
case -1472899494:
|
|
if (var6.submit(var1, var2, var3, var4, ti.INSTANCE.jpegQuality())) {
|
|
var7 = 1714758591;
|
|
} else {
|
|
var7 = -2101731117;
|
|
}
|
|
break;
|
|
case 113816286:
|
|
return (boolean)((var8) != 0);
|
|
case 1714758591:
|
|
var8 = 1;
|
|
var7 = 113816286;
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void discard(byte[] var1) {
|
|
this.pixels.recycle(var1);
|
|
}
|
|
|
|
@Override
|
|
public void onFrame(int var1, int var2, akb var3) {
|
|
if (var1 != this.frameWidth || var2 != this.frameHeight) {
|
|
this.frameWidth = var1;
|
|
this.frameHeight = var2;
|
|
this.ring.clear();
|
|
if (this.recording) {
|
|
this.stopRecording();
|
|
}
|
|
}
|
|
|
|
aje var4 = aje.getInstance();
|
|
var4.onFrame(var1, var2, var3);
|
|
if (ti.INSTANCE.instantReplay.isEnabled() && !var4.isActive()) {
|
|
this.ring.add(var3);
|
|
}
|
|
|
|
synchronized (this.writerLock) {
|
|
if (this.writer != null) {
|
|
try {
|
|
this.writer.append(var3);
|
|
} catch (IOException var8) {
|
|
id.error(Cif.MEDIA, "clip recording failed", var8);
|
|
this.closeWriterLocked();
|
|
this.recording = (boolean)(((0)) != 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void onAudio(ajr var1) {
|
|
if (ti.INSTANCE.instantReplay.isEnabled()) {
|
|
this.audioRing.add(var1);
|
|
}
|
|
|
|
synchronized (this.writerLock) {
|
|
if (this.writer != null) {
|
|
try {
|
|
this.writer.appendAudio(var1);
|
|
} catch (IOException var5) {
|
|
id.error(Cif.MEDIA, "clip recording failed", var5);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void syncAudioCapture(ti var1) {
|
|
int var2 = var1.gameAudio.isEnabled() && !this.systemAudioFailed
|
|
? 1: 0;
|
|
int var3 = var1.microphone.isEnabled() && !this.microphoneFailed
|
|
? 1: 0;
|
|
if (var2
|
|
!= (
|
|
this.systemAudio != null
|
|
? 1: (1992414113 ^ -1992414113) + ((1992414113 & -1992414113) << 1)
|
|
)
|
|
|| var3
|
|
!= (
|
|
this.microphoneAudio != null
|
|
? 1: (-1007646925 ^ 1007646925) + ((-1007646925 & 1007646925) << 1)
|
|
)) {
|
|
String var4 = var1.gameAudioDevice();
|
|
String var5 = var1.microphoneDevice();
|
|
int var6 = var4 != null && var4.equals(var5)
|
|
? 1: 0;
|
|
this.io
|
|
.execute(
|
|
() -> {
|
|
if (var2 == 0 && this.systemAudio != null) {
|
|
this.systemAudio.close();
|
|
this.systemAudio = null;
|
|
}
|
|
|
|
if (var3 == 0 && this.microphoneAudio != null) {
|
|
this.microphoneAudio.close();
|
|
this.microphoneAudio = null;
|
|
}
|
|
|
|
if (var3 != 0 && this.microphoneAudio == null) {
|
|
this.microphoneAudio = this.openAudio(1, var5);
|
|
this.microphoneFailed = (boolean)(((this.microphoneAudio == null
|
|
? 1: (1683764292 ^ -1683764292) + ((1683764292 & -1683764292) << 1))) != 0);
|
|
}
|
|
|
|
if (var2 != 0 && this.systemAudio == null) {
|
|
if (var4 == null) {
|
|
this.systemAudioFailed = (boolean)(((1)) != 0);
|
|
notifyStatus(
|
|
"game audio needs a loopback device"
|
|
);
|
|
} else if (var6 != 0 && this.microphoneAudio != null) {
|
|
this.systemAudioFailed = (boolean)(((1)) != 0);
|
|
notifyStatus("game audio needs a loopback device");
|
|
} else {
|
|
this.systemAudio = this.openAudio(0, var4);
|
|
this.systemAudioFailed = (boolean)(((this.systemAudio == null
|
|
? 1: (31052517 ^ -31052517) + ((31052517 & -31052517) << 1))) != 0);
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
private ajq openAudio(int var1, String var2) {
|
|
if (var2 == null) {
|
|
notifyStatus("audio device unavailable");
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
ajq var3 = new ajq(var1, var2, this::onAudio);
|
|
var3.start(System.currentTimeMillis());
|
|
return var3;
|
|
} catch (LineUnavailableException | RuntimeException var4) {
|
|
id.error(
|
|
Cif.MEDIA,
|
|
"clip audio capture unavailable for channel {}",
|
|
var1,
|
|
var4
|
|
);
|
|
notifyStatus("audio device unavailable");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private void closeAudio() {
|
|
int var1 = 46666817;
|
|
|
|
while (true) {
|
|
switch (var1) {
|
|
case -1012708051:
|
|
this.microphoneAudio.close();
|
|
this.microphoneAudio = null;
|
|
var1 = 54512945;
|
|
break;
|
|
case -72612598:
|
|
this.systemAudio.close();
|
|
this.systemAudio = null;
|
|
var1 = 535564911;
|
|
break;
|
|
case 46666817:
|
|
default:
|
|
if (this.systemAudio != null) {
|
|
var1 = -72612598;
|
|
} else {
|
|
var1 = 535564911;
|
|
}
|
|
break;
|
|
case 54512945:
|
|
this.systemAudioFailed = (boolean)(((0)) != 0);
|
|
this.microphoneFailed = (boolean)(((0)) != 0);
|
|
this.audioRing.clear();
|
|
return;
|
|
case 535564911:
|
|
if (this.microphoneAudio != null) {
|
|
var1 = -1012708051;
|
|
} else {
|
|
var1 = 54512945;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void saveInstantReplay() {
|
|
List var1 = null;
|
|
List var2 = null;
|
|
int var3 = 0;
|
|
int var4 = 0;
|
|
int var5 = 0;
|
|
int var6 = 985883918;
|
|
|
|
while (true) {
|
|
switch (var6) {
|
|
case -857498035:
|
|
var2 = this.audioRing.snapshot(((akb)var1.getFirst()).timestampMillis(), ((akb)var1.getLast()).timestampMillis());
|
|
var3 = this.frameWidth;
|
|
var4 = this.frameHeight;
|
|
var5 = ti.INSTANCE.captureFps();
|
|
this.saving = (boolean)(((1)) != 0);
|
|
this.io.execute(() -> this.writeClip(var1, var2, var3, var4, var5));
|
|
return;
|
|
case -411039100:
|
|
var1 = this.ring.snapshot();
|
|
if (var1.size() < (1727226768 ^ -1727226766) + ((1727226768 & -1727226766) << 1)) {
|
|
var6 = -242760839;
|
|
} else {
|
|
var6 = -857498035;
|
|
}
|
|
break;
|
|
case -242760839:
|
|
notifyStatus("buffer is empty");
|
|
return;
|
|
case 985883918:
|
|
default:
|
|
if (this.saving) {
|
|
var6 = 1626806322;
|
|
} else {
|
|
var6 = -411039100;
|
|
}
|
|
break;
|
|
case 1626806322:
|
|
notifyStatus("already working");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void toggleRecording() {
|
|
int var1 = 1831475424;
|
|
|
|
while (true) {
|
|
switch (var1) {
|
|
case -1927287706:
|
|
this.startRecording();
|
|
var1 = 487530995;
|
|
break;
|
|
case -699861389:
|
|
this.stopRecording();
|
|
var1 = 487530995;
|
|
break;
|
|
case 487530995:
|
|
return;
|
|
case 1831475424:
|
|
default:
|
|
if (this.recording) {
|
|
var1 = -699861389;
|
|
} else {
|
|
var1 = -1927287706;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void startRecording() {
|
|
int var1 = 0;
|
|
int var2 = 0;
|
|
int var3 = 0;
|
|
int var4 = -702390882;
|
|
|
|
while (true) {
|
|
switch (var4) {
|
|
case -1786782579:
|
|
notifyStatus("already working");
|
|
return;
|
|
case -1113527304:
|
|
var1 = this.frameWidth;
|
|
var2 = this.frameHeight;
|
|
var3 = ti.INSTANCE.captureFps();
|
|
this.recording = (boolean)(((1)) != 0);
|
|
this.recordingStartedMillis = System.currentTimeMillis();
|
|
this.io.execute(() -> this.openWriter(var1, var2, var3));
|
|
notifyStatus("recording");
|
|
return;
|
|
case -702390882:
|
|
default:
|
|
if (!this.recording) {
|
|
var4 = 1164277836;
|
|
} else {
|
|
var4 = -1786782579;
|
|
}
|
|
break;
|
|
case 1164277836:
|
|
if (this.saving) {
|
|
var4 = -1786782579;
|
|
} else {
|
|
var4 = -1113527304;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void stopRecording() {
|
|
this.stopRecording((boolean)((((-899973690 | 899973690) + (-899973690 & 899973690))) != 0));
|
|
}
|
|
|
|
public void stopRecording(boolean var1) {
|
|
int var2 = -2042369646;
|
|
|
|
while (true) {
|
|
switch (var2) {
|
|
case -2042369646:
|
|
default:
|
|
if (!this.recording) {
|
|
var2 = 1576689565;
|
|
} else {
|
|
var2 = -847555136;
|
|
}
|
|
break;
|
|
case -847555136:
|
|
this.recording = (boolean)(((0)) != 0);
|
|
this.forcedExport = var1;
|
|
this.io.execute(this::finishRecording);
|
|
return;
|
|
case 1576689565:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void export(ake var1, int var2, int var3) {
|
|
int var4 = -879081490;
|
|
|
|
while (true) {
|
|
switch (var4) {
|
|
case -2010159792:
|
|
this.exporting = (boolean)(((1)) != 0);
|
|
this.exportProgress = 0.0F;
|
|
this.exports.execute(() -> this.runExport(var1, var2, var3, this.library.allocateExport(var1.name())));
|
|
return;
|
|
case -879081490:
|
|
default:
|
|
if (this.exporting) {
|
|
var4 = 357208169;
|
|
} else {
|
|
var4 = -2010159792;
|
|
}
|
|
break;
|
|
case 357208169:
|
|
notifyStatus("already working");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void exportAs(ake var1, int var2, int var3) {
|
|
int var4 = 1766889993;
|
|
|
|
while (true) {
|
|
switch (var4) {
|
|
case -46915276:
|
|
this.exporting = (boolean)(((1)) != 0);
|
|
this.exportProgress = 0.0F;
|
|
this.exports.execute(() -> {
|
|
Path var4x = null;
|
|
int var5 = -1440358899;
|
|
|
|
while (true) {
|
|
switch (var5) {
|
|
case -1756571626:
|
|
this.runExport(var1, var2, var3, var4x);
|
|
return;
|
|
case -1440358899:
|
|
default:
|
|
var4x = chooseTarget(this.library.allocateExport(var1.name()));
|
|
if (var4x == null) {
|
|
var5 = 657811488;
|
|
} else {
|
|
var5 = -1756571626;
|
|
}
|
|
break;
|
|
case 657811488:
|
|
this.exporting = (boolean)(((0)) != 0);
|
|
notifyStatus("export cancelled");
|
|
return;
|
|
}
|
|
}
|
|
});
|
|
return;
|
|
case 1702042761:
|
|
notifyStatus("already working");
|
|
return;
|
|
case 1766889993:
|
|
}
|
|
|
|
if (this.exporting) {
|
|
var4 = 1702042761;
|
|
} else {
|
|
var4 = -46915276;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static Path chooseTarget(Path var0) {
|
|
try {
|
|
MemoryStack var1 = MemoryStack.stackPush();
|
|
|
|
Path var4;
|
|
try {
|
|
PointerBuffer var2 = var1.mallocPointer((402000002 ^ -402000001) + ((402000002 & -402000001) << 1));
|
|
var2.put(var1.UTF8("*.mp4"));
|
|
var2.flip();
|
|
String var3 = TinyFileDialogs.tinyfd_saveFileDialog(
|
|
"Save clip",
|
|
var0.toString(),
|
|
var2,
|
|
"MP4 video"
|
|
);
|
|
var4 = var3 != null && !var3.isBlank() ? Path.of(var3) : null;
|
|
} catch (Throwable var6) {
|
|
if (var1 != null) {
|
|
try {
|
|
var1.close();
|
|
} catch (Throwable var5) {
|
|
var6.addSuppressed(var5);
|
|
}
|
|
}
|
|
|
|
throw var6;
|
|
}
|
|
|
|
if (var1 != null) {
|
|
var1.close();
|
|
}
|
|
|
|
return var4;
|
|
} catch (Throwable var7) {
|
|
id.error(Cif.MEDIA, "clip export failed", var7);
|
|
return var0;
|
|
}
|
|
}
|
|
|
|
public void shutdown() {
|
|
this.stopRecording();
|
|
this.io.execute(this::stopEncoders);
|
|
aqg.mc.execute(ajl::release);
|
|
}
|
|
|
|
private void stopEncoders() {
|
|
synchronized (this.poolLock) {
|
|
ajj var2 = this.encoders;
|
|
if (var2 != null) {
|
|
var2.flush((1837848887167015651L ^ -1837848887167012651L) + ((1837848887167015651L & -1837848887167012651L) << 1));
|
|
var2.stop();
|
|
this.encoders = null;
|
|
}
|
|
}
|
|
|
|
this.ring.clear();
|
|
this.pixels.clear();
|
|
this.closeAudio();
|
|
}
|
|
|
|
private void startEncoders() {
|
|
int var1 = desiredWorkers();
|
|
ajj var2 = this.encoders;
|
|
if (var2 == null || !var2.isRunning() || var2.workerCount() != var1) {
|
|
synchronized (this.poolLock) {
|
|
if (this.encoders != null && this.encoders.workerCount() != var1) {
|
|
this.encoders.stop();
|
|
this.encoders = null;
|
|
}
|
|
|
|
if (this.encoders == null) {
|
|
this.encoders = new ajj(this, this.pixels, var1);
|
|
}
|
|
|
|
if (!this.encoders.isRunning()) {
|
|
this.encoders.start();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static int desiredWorkers() {
|
|
int var0 = Math.round(ti.INSTANCE.captureFps() / 30.0F);
|
|
int var1 = Runtime.getRuntime().availableProcessors() / (2);
|
|
return Math.clamp(
|
|
Math.min(var0, var1), 1, (103338153 ^ -103338149) + ((103338153 & -103338149) << 1)
|
|
);
|
|
}
|
|
|
|
private void writeClip(List<akb> var1, List<ajr> var2, int var3, int var4, int var5) {
|
|
Path var6 = this.library.allocateClip(((akb)var1.getFirst()).timestampMillis());
|
|
|
|
try (ajz var7 = new ajz(var6, var3, var4, var5, ((akb)var1.getFirst()).timestampMillis())) {
|
|
var7.appendAll(var1);
|
|
var7.appendAllAudio(var2);
|
|
} catch (IOException var12) {
|
|
this.saving = (boolean)(((0)) != 0);
|
|
id.error(Cif.MEDIA, "clip save failed", var12);
|
|
notifyStatus("failed");
|
|
return;
|
|
}
|
|
|
|
this.saving = (boolean)(((0)) != 0);
|
|
this.library.prune(ti.INSTANCE.storageBytes());
|
|
this.announceClip(var6, "saved");
|
|
}
|
|
|
|
private void openWriter(int var1, int var2, int var3) {
|
|
long var4 = System.currentTimeMillis();
|
|
Path var6 = this.library.allocateClip(var4);
|
|
|
|
try {
|
|
ajz var7 = new ajz(var6, var1, var2, var3, var4);
|
|
synchronized (this.writerLock) {
|
|
this.writer = var7;
|
|
}
|
|
} catch (IOException var11) {
|
|
this.recording = (boolean)(((0)) != 0);
|
|
id.error(Cif.MEDIA, "clip recording failed", var11);
|
|
notifyStatus("failed");
|
|
}
|
|
}
|
|
|
|
private void finishRecording() {
|
|
ajj var1 = this.encoders;
|
|
if (var1 != null) {
|
|
var1.flushTo(var1.submittedSequence(), (-3082258856859192361L ^ 3082258856859195361L) + ((-3082258856859192361L & 3082258856859195361L) << 1));
|
|
}
|
|
|
|
Path var2;
|
|
synchronized (this.writerLock) {
|
|
if (this.writer == null) {
|
|
return;
|
|
}
|
|
|
|
var2 = this.writer.path();
|
|
this.closeWriterLocked();
|
|
}
|
|
|
|
this.library.prune(ti.INSTANCE.storageBytes());
|
|
this.announceClip(var2, "recording saved");
|
|
}
|
|
|
|
private void closeWriterLocked() {
|
|
try {
|
|
this.writer.close();
|
|
} catch (IOException var5) {
|
|
id.error(Cif.MEDIA, "clip recording failed", var5);
|
|
} finally {
|
|
this.writer = null;
|
|
}
|
|
}
|
|
|
|
private void announceClip(Path var1, String var2) {
|
|
ake var3;
|
|
try {
|
|
var3 = aka.readMeta(var1);
|
|
} catch (IOException var6) {
|
|
id.error(Cif.MEDIA, "clip save failed", var6);
|
|
notifyStatus("failed");
|
|
return;
|
|
}
|
|
|
|
notifyStatus(var2 + " " + elapsed(var3.durationMillis()));
|
|
playSavedSound();
|
|
ti var4 = ti.INSTANCE;
|
|
boolean var5 = this.forcedExport;
|
|
this.forcedExport = (boolean)(((0)) != 0);
|
|
if ((var4.autoExport.isEnabled() || var5) && var3.frameCount() > (2047021825 ^ -2047021824) + ((2047021825 & -2047021824) << 1)) {
|
|
this.export(
|
|
var3, 0, var3.frameCount() - ((1153039940 ^ -1153039939) + ((1153039940 & -1153039939) << 1))
|
|
);
|
|
}
|
|
|
|
if (var4.openEditor.isEnabled()) {
|
|
aqg.mc.execute(() -> aby.open(var3));
|
|
}
|
|
}
|
|
|
|
// $VF: Could not verify finally blocks. A semaphore variable has been added to preserve control flow.
|
|
// Please report this to the Vineflower issue tracker, at https://github.com/Vineflower/vineflower/issues with a copy of the class file (if you have the rights to distribute it!)
|
|
private void runExport(ake var1, int var2, int var3, Path var4) {
|
|
int var5 = 0;
|
|
boolean var15 = false /* VF: Semaphore variable */;
|
|
|
|
label65: {
|
|
label64: {
|
|
try {
|
|
var15 = true;
|
|
|
|
try (ajy var6 = new ajy(var1.path())) {
|
|
ti var7 = ti.INSTANCE;
|
|
int var8 = Math.max(15, var7.exportFps());
|
|
ajw var9 = new ajw(var7.exportQuantizer(), var7.exportThreads(), var8, var7.exportFps());
|
|
var5 = (ajx.export(
|
|
var6,
|
|
Math.max(0, var2),
|
|
Math.min(var3, var6.frameCount() - ((-1066600019 ^ 1066600020) + ((-1066600019 & 1066600020) << 1))),
|
|
var4,
|
|
var9,
|
|
this.listener()
|
|
)) ? 1 : 0;
|
|
}
|
|
|
|
var15 = false;
|
|
break label64;
|
|
} catch (IOException var18) {
|
|
id.error(
|
|
Cif.MEDIA, "clip export failed", var18
|
|
);
|
|
var15 = false;
|
|
} finally {
|
|
if (var15) {
|
|
this.exporting = (boolean)(((0)) != 0);
|
|
this.exportProgress = 0.0F;
|
|
}
|
|
}
|
|
|
|
this.exporting = (boolean)(((0)) != 0);
|
|
this.exportProgress = 0.0F;
|
|
break label65;
|
|
}
|
|
|
|
this.exporting = (boolean)(((0)) != 0);
|
|
this.exportProgress = 0.0F;
|
|
}
|
|
|
|
notifyStatus(
|
|
var5 != 0
|
|
? "exported"
|
|
: "failed"
|
|
);
|
|
}
|
|
|
|
private ajv listener() {
|
|
return new ajv() {
|
|
@Override
|
|
public void onProgress(float var1) {
|
|
ajn.this.exportProgress = var1;
|
|
}
|
|
|
|
@Override
|
|
public boolean cancelled() {
|
|
return (boolean)(((0)) != 0);
|
|
}
|
|
};
|
|
}
|
|
|
|
private static void playSavedSound() {
|
|
aqg.mc.execute(() -> {
|
|
mm var0 = null;
|
|
int var1 = 541190834;
|
|
|
|
while (true) {
|
|
switch (var1) {
|
|
case 541190834:
|
|
default:
|
|
var0 = bz.getInstance().getSoundManager();
|
|
if (var0 != null) {
|
|
var1 = 911639411;
|
|
} else {
|
|
var1 = 1669065045;
|
|
}
|
|
break;
|
|
case 911639411:
|
|
var0.play(mj.CLIP_SAVED);
|
|
var1 = 1669065045;
|
|
break;
|
|
case 1669065045:
|
|
return;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
static void notifyStatus(String var0) {
|
|
aqg.mc
|
|
.execute(
|
|
() -> le.getInstance()
|
|
.addCustomNotification(rl.MISC.getIcon(), "Clips", var0)
|
|
);
|
|
}
|
|
|
|
public static String elapsed(long var0) {
|
|
long var2 = Math.max((-4278841967973501350L | 4278841967973501350L) + (-4278841967973501350L & 4278841967973501350L), var0)
|
|
/ ((6702982416488184899L ^ -6702982416488183899L) + ((6702982416488184899L & -6702982416488183899L) << 1));
|
|
long var4 = var2 / ((-7061273179146511698L ^ 7061273179146511758L) + ((-7061273179146511698L & 7061273179146511758L) << 1));
|
|
long var6 = var2 % ((8277252237356953933L ^ -8277252237356953873L) + ((8277252237356953933L & -8277252237356953873L) << 1));
|
|
return var4
|
|
+ ":"
|
|
+ (var6 < (1037647348913914466L | -1037647348913914456L) + (1037647348913914466L & -1037647348913914456L) ? "0" + var6 : Long.toString(var6));
|
|
}
|
|
|
|
private static ThreadFactory factory(String var0) {
|
|
return var1 -> {
|
|
Thread var2 = new Thread(var1, var0);
|
|
var2.setDaemon((boolean)((((-1506489619 | 1506489620) + (-1506489619 & 1506489620))) != 0));
|
|
return var2;
|
|
};
|
|
}
|
|
}
|