aboutsummaryrefslogtreecommitdiff
path: root/app/src/test/java
diff options
context:
space:
mode:
authorLena <lena@omega>2026-08-01 00:00:00 +0000
committerLena <lena@omega>2026-08-01 00:00:00 +0000
commit75b1a5569bf9048acefa49f2921b2653a828d545 (patch)
tree1b0342936b71ac5e5f59ad3b4e1e37cea2691ff5 /app/src/test/java
parent4ea99f1b77ba547014fb7b7becaa8de2fd671a0b (diff)
downloadscrcpy-android-75b1a5569bf9048acefa49f2921b2653a828d545.tar.gz
audio: harden Opus playback
Preserve decoder timing and keep blocking speaker writes off codec callbacks. Playback failures no longer take down video or control.
Diffstat (limited to 'app/src/test/java')
-rw-r--r--app/src/test/java/invalid/lena/scrcpy/AudioStreamTest.java41
1 files changed, 30 insertions, 11 deletions
diff --git a/app/src/test/java/invalid/lena/scrcpy/AudioStreamTest.java b/app/src/test/java/invalid/lena/scrcpy/AudioStreamTest.java
index 005a2e3..1fca17c 100644
--- a/app/src/test/java/invalid/lena/scrcpy/AudioStreamTest.java
+++ b/app/src/test/java/invalid/lena/scrcpy/AudioStreamTest.java
@@ -11,21 +11,24 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
public class AudioStreamTest {
private static final long FLAG_CONFIG = 1L << 62;
+ private static final long FLAG_KEYFRAME = 1L << 61;
private static final class RecordingFrames implements AudioFrames {
int starts = 0, releases = 0, startFourcc = 0;
final List<byte[]> feeds = new ArrayList<>();
+ final List<Long> pts = new ArrayList<>();
final List<Boolean> cfgs = new ArrayList<>();
@Override public void start(int fourcc) { starts++; startFourcc = fourcc; }
- @Override public void feed(byte[] data, int off, int len, boolean isConfig) {
+ @Override public void feed(byte[] data, int off, int len,
+ long ptsUs, boolean isConfig) {
byte[] cp = new byte[len];
System.arraycopy(data, off, cp, 0, len);
feeds.add(cp);
+ pts.add(ptsUs);
cfgs.add(isConfig);
}
@Override public void release() { releases++; }
@@ -73,6 +76,8 @@ public class AudioStreamTest {
for (int i = 0; i < pcm2.length; i++) assertEquals(pcm2[i], sink.feeds.get(1)[i]);
assertEquals(false, sink.cfgs.get(0));
assertEquals(false, sink.cfgs.get(1));
+ assertEquals(Long.valueOf(1_000_000L), sink.pts.get(0));
+ assertEquals(Long.valueOf(2_000_000L), sink.pts.get(1));
}
@Test
@@ -90,7 +95,7 @@ public class AudioStreamTest {
byte[] bytes = cat(
fourcc(Wire.CODEC_OPUS),
frame(FLAG_CONFIG, head),
- frame(0L, pkt));
+ frame(FLAG_KEYFRAME | 3_000_000L, pkt));
RecordingFrames sink = new RecordingFrames();
new AudioStream(new ByteArrayInputStream(bytes), sink).run();
@@ -102,6 +107,8 @@ public class AudioStreamTest {
assertTrue("second frame must not carry FLAG_CONFIG", !sink.cfgs.get(1));
assertEquals(head.length, sink.feeds.get(0).length);
assertEquals(pkt.length, sink.feeds.get(1).length);
+ assertEquals(Long.valueOf(0L), sink.pts.get(0));
+ assertEquals(Long.valueOf(3_000_000L), sink.pts.get(1));
}
@Test
@@ -117,18 +124,30 @@ public class AudioStreamTest {
public void errorCodecDoesNotStart() throws Exception {
byte[] bytes = fourcc(1);
RecordingFrames sink = new RecordingFrames();
- AtomicInteger fatal = new AtomicInteger();
- new AudioStream(new ByteArrayInputStream(bytes), sink, fatal::incrementAndGet).run();
+ new AudioStream(new ByteArrayInputStream(bytes), sink).run();
assertEquals(0, sink.starts);
assertEquals(0, sink.feeds.size());
- assertEquals(1, fatal.get());
}
@Test
- public void disabledCodecIsNotFatal() throws Exception {
- AtomicInteger fatal = new AtomicInteger();
- new AudioStream(new ByteArrayInputStream(fourcc(0)),
- new RecordingFrames(), fatal::incrementAndGet).run();
- assertEquals(0, fatal.get());
+ public void outputFailureStillDrainsWire() throws Exception {
+ byte[] bytes = cat(
+ fourcc(Wire.CODEC_RAW),
+ frame(1_000_000L, new byte[]{1, 2, 3, 4}));
+ ByteArrayInputStream in = new ByteArrayInputStream(bytes);
+ AudioFrames sink = new AudioFrames() {
+ @Override public void start(int fourcc) {
+ throw new IllegalStateException("no audio output");
+ }
+ @Override public void feed(byte[] data, int off, int len,
+ long ptsUs, boolean isConfig) {
+ throw new AssertionError("disabled output must not receive frames");
+ }
+ @Override public void release() {}
+ };
+
+ new AudioStream(in, sink).run();
+
+ assertEquals(0, in.available());
}
}