1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
package invalid.lena.scrcpy;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
// Byte-order helpers used everywhere we touch raw streams.
//
// scrcpy server framing is big-endian (java standard).
// adb sync framing is little-endian (legacy).
//
// FOURCCs are read as a big-endian uint32, which matches the literal
// 4-char ASCII tag, so '"h264"' becomes 0x68323634.
public final class Wire {
private Wire() {}
// ---- big-endian (scrcpy) ----
public static int readBe32(byte[] b, int off) {
return ((b[off] & 0xff) << 24)
| ((b[off + 1] & 0xff) << 16)
| ((b[off + 2] & 0xff) << 8)
| (b[off + 3] & 0xff);
}
public static long readBe64(byte[] b, int off) {
return ((long)(readBe32(b, off)) << 32) | (readBe32(b, off + 4) & 0xffffffffL);
}
public static void writeBe32(byte[] b, int off, int v) {
b[off] = (byte)(v >>> 24);
b[off + 1] = (byte)(v >>> 16);
b[off + 2] = (byte)(v >>> 8);
b[off + 3] = (byte) v;
}
public static void writeBe64(byte[] b, int off, long v) {
writeBe32(b, off, (int)(v >>> 32));
writeBe32(b, off + 4, (int) v);
}
// ---- little-endian (adb sync) ----
public static int readLe32(byte[] b, int off) {
return (b[off] & 0xff)
| ((b[off + 1] & 0xff) << 8)
| ((b[off + 2] & 0xff) << 16)
| ((b[off + 3] & 0xff) << 24);
}
public static void writeLe32(byte[] b, int off, int v) {
b[off] = (byte) v;
b[off + 1] = (byte)(v >>> 8);
b[off + 2] = (byte)(v >>> 16);
b[off + 3] = (byte)(v >>> 24);
}
// ---- I/O helpers ----
public static void readFully(InputStream in, byte[] buf, int off, int len) throws IOException {
int got = 0;
while (got < len) {
int n = in.read(buf, off + got, len - got);
if (n < 0) throw new EOFException(
"short read: wanted " + len + " got " + got);
got += n;
}
}
public static void readFully(InputStream in, byte[] buf) throws IOException {
readFully(in, buf, 0, buf.length);
}
// scrcpy codec identifiers, mirrored from com.genymobile.scrcpy.{video,audio}.*Codec.
// Short names (raw, aac) are NUL-padded on the left, not space-padded on the right.
// Declared as int-literal constants so they can drive switch-case labels.
public static final int CODEC_H264 = 0x68_32_36_34; // 'h264'
public static final int CODEC_H265 = 0x68_32_36_35; // 'h265'
public static final int CODEC_AV1 = 0x61_76_30_31; // 'av01'
public static final int CODEC_OPUS = 0x6f_70_75_73; // 'opus'
public static final int CODEC_FLAC = 0x66_6c_61_63; // 'flac'
public static final int CODEC_AAC = 0x00_61_61_63; // '\0aac'
public static final int CODEC_RAW = 0x00_72_61_77; // '\0raw'
public static String fourccName(int v) {
// Skip any leading NUL bytes - scrcpy left-pads short names like
// 'raw' and 'aac' with \0, which would otherwise render as
// non-printable characters in logs.
char[] cs = new char[]{
(char)((v >>> 24) & 0xff),
(char)((v >>> 16) & 0xff),
(char)((v >>> 8) & 0xff),
(char)( v & 0xff)};
int from = 0;
while (from < cs.length && cs[from] == 0) from++;
return new String(cs, from, cs.length - from);
}
}
|