@yume-chan/scrcpy 0.0.19 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +30 -0
- package/CHANGELOG.md +17 -1
- package/README.md +76 -266
- package/esm/codec/av1.js +2 -2
- package/esm/codec/av1.js.map +1 -1
- package/esm/codec/h264.d.ts +1 -21
- package/esm/codec/h264.d.ts.map +1 -1
- package/esm/codec/h264.js +15 -236
- package/esm/codec/h264.js.map +1 -1
- package/esm/codec/h265.d.ts +454 -0
- package/esm/codec/h265.d.ts.map +1 -1
- package/esm/codec/h265.js +1062 -2
- package/esm/codec/h265.js.map +1 -1
- package/esm/codec/index.d.ts +1 -0
- package/esm/codec/index.d.ts.map +1 -1
- package/esm/codec/index.js +1 -0
- package/esm/codec/index.js.map +1 -1
- package/esm/codec/nalu.d.ts +37 -0
- package/esm/codec/nalu.d.ts.map +1 -0
- package/esm/codec/nalu.js +323 -0
- package/esm/codec/nalu.js.map +1 -0
- package/esm/control/back-or-screen-on.d.ts +1 -1
- package/esm/control/back-or-screen-on.d.ts.map +1 -1
- package/esm/control/hover-helper.d.ts +1 -1
- package/esm/control/hover-helper.d.ts.map +1 -1
- package/esm/control/hover-helper.js +8 -9
- package/esm/control/hover-helper.js.map +1 -1
- package/esm/control/index.d.ts +2 -0
- package/esm/control/index.d.ts.map +1 -1
- package/esm/control/index.js +2 -0
- package/esm/control/index.js.map +1 -1
- package/esm/control/inject-keycode.d.ts +1 -2
- package/esm/control/inject-keycode.d.ts.map +1 -1
- package/esm/control/inject-keycode.js +4 -5
- package/esm/control/inject-keycode.js.map +1 -1
- package/esm/control/inject-text.d.ts +1 -2
- package/esm/control/inject-text.d.ts.map +1 -1
- package/esm/control/inject-text.js +1 -2
- package/esm/control/inject-text.js.map +1 -1
- package/esm/control/inject-touch.d.ts +15 -20
- package/esm/control/inject-touch.d.ts.map +1 -1
- package/esm/control/inject-touch.js +16 -43
- package/esm/control/inject-touch.js.map +1 -1
- package/esm/control/rotate-device.d.ts +2 -4
- package/esm/control/rotate-device.d.ts.map +1 -1
- package/esm/control/rotate-device.js +2 -3
- package/esm/control/rotate-device.js.map +1 -1
- package/esm/control/serializer.d.ts +11 -23
- package/esm/control/serializer.d.ts.map +1 -1
- package/esm/control/serializer.js +23 -52
- package/esm/control/serializer.js.map +1 -1
- package/esm/control/set-screen-power-mode.d.ts +1 -2
- package/esm/control/set-screen-power-mode.d.ts.map +1 -1
- package/esm/control/set-screen-power-mode.js +2 -3
- package/esm/control/set-screen-power-mode.js.map +1 -1
- package/esm/control/type.d.ts +14 -0
- package/esm/control/type.d.ts.map +1 -1
- package/esm/control/type.js +23 -1
- package/esm/control/type.js.map +1 -1
- package/esm/control/writer.d.ts +26 -0
- package/esm/control/writer.d.ts.map +1 -0
- package/esm/control/writer.js +53 -0
- package/esm/control/writer.js.map +1 -0
- package/esm/device-message/stream.d.ts.map +1 -1
- package/esm/device-message/stream.js +23 -8
- package/esm/device-message/stream.js.map +1 -1
- package/esm/device-message/type.js +1 -1
- package/esm/device-message/type.js.map +1 -1
- package/esm/index.d.ts +1 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -2
- package/esm/index.js.map +1 -1
- package/esm/options/1_16/codec-options.d.ts +2 -3
- package/esm/options/1_16/codec-options.d.ts.map +1 -1
- package/esm/options/1_16/codec-options.js.map +1 -1
- package/esm/options/1_16/index.d.ts +3 -1
- package/esm/options/1_16/index.d.ts.map +1 -1
- package/esm/options/1_16/index.js +3 -1
- package/esm/options/1_16/index.js.map +1 -1
- package/esm/options/1_16/init.js +2 -2
- package/esm/options/1_16/init.js.map +1 -1
- package/esm/options/1_16/options.d.ts +42 -96
- package/esm/options/1_16/options.d.ts.map +1 -1
- package/esm/options/1_16/options.js +104 -142
- package/esm/options/1_16/options.js.map +1 -1
- package/esm/options/1_16/scroll.d.ts +2 -4
- package/esm/options/1_16/scroll.d.ts.map +1 -1
- package/esm/options/1_16/scroll.js +13 -14
- package/esm/options/1_16/scroll.js.map +1 -1
- package/esm/options/1_17.d.ts +1 -0
- package/esm/options/1_17.d.ts.map +1 -1
- package/esm/options/1_17.js +8 -3
- package/esm/options/1_17.js.map +1 -1
- package/esm/options/1_18.d.ts +49 -11
- package/esm/options/1_18.d.ts.map +1 -1
- package/esm/options/1_18.js +64 -32
- package/esm/options/1_18.js.map +1 -1
- package/esm/options/1_21.d.ts +26 -7
- package/esm/options/1_21.d.ts.map +1 -1
- package/esm/options/1_21.js +34 -20
- package/esm/options/1_21.js.map +1 -1
- package/esm/options/1_22/index.d.ts +1 -0
- package/esm/options/1_22/index.d.ts.map +1 -1
- package/esm/options/1_22/index.js +1 -0
- package/esm/options/1_22/index.js.map +1 -1
- package/esm/options/1_22/options.d.ts +32 -26
- package/esm/options/1_22/options.d.ts.map +1 -1
- package/esm/options/1_22/options.js +26 -16
- package/esm/options/1_22/options.js.map +1 -1
- package/esm/options/1_22/scroll.d.ts +1 -1
- package/esm/options/1_22/scroll.d.ts.map +1 -1
- package/esm/options/1_22/scroll.js +1 -1
- package/esm/options/1_22/scroll.js.map +1 -1
- package/esm/options/1_23.d.ts +32 -8
- package/esm/options/1_23.d.ts.map +1 -1
- package/esm/options/1_23.js +23 -14
- package/esm/options/1_23.js.map +1 -1
- package/esm/options/1_24.d.ts +29 -4
- package/esm/options/1_24.d.ts.map +1 -1
- package/esm/options/1_24.js +16 -7
- package/esm/options/1_24.js.map +1 -1
- package/esm/options/1_25/options.d.ts +6 -2
- package/esm/options/1_25/options.d.ts.map +1 -1
- package/esm/options/1_25/options.js +16 -2
- package/esm/options/1_25/options.js.map +1 -1
- package/esm/options/1_25/scroll.d.ts.map +1 -1
- package/esm/options/1_25/scroll.js +2 -1
- package/esm/options/1_25/scroll.js.map +1 -1
- package/esm/options/2_0.d.ts +12 -8
- package/esm/options/2_0.d.ts.map +1 -1
- package/esm/options/2_0.js +82 -15
- package/esm/options/2_0.js.map +1 -1
- package/esm/options/2_1.d.ts +48 -0
- package/esm/options/2_1.d.ts.map +1 -0
- package/esm/options/2_1.js +23 -0
- package/esm/options/2_1.js.map +1 -0
- package/esm/options/codec.d.ts +4 -4
- package/esm/options/codec.d.ts.map +1 -1
- package/esm/options/codec.js +5 -6
- package/esm/options/codec.js.map +1 -1
- package/esm/options/index.d.ts +5 -0
- package/esm/options/index.d.ts.map +1 -1
- package/esm/options/index.js +5 -0
- package/esm/options/index.js.map +1 -1
- package/esm/options/latest.d.ts +4 -5
- package/esm/options/latest.d.ts.map +1 -1
- package/esm/options/latest.js +2 -3
- package/esm/options/latest.js.map +1 -1
- package/esm/options/types.d.ts +74 -33
- package/esm/options/types.d.ts.map +1 -1
- package/esm/options/types.js +62 -0
- package/esm/options/types.js.map +1 -1
- package/package.json +9 -19
- package/src/codec/av1.ts +33 -0
- package/src/codec/h264.ts +317 -0
- package/src/codec/h265.ts +1375 -0
- package/src/codec/index.ts +4 -0
- package/src/codec/nalu.ts +391 -0
- package/src/control/back-or-screen-on.ts +1 -1
- package/{esm/control/simple.js → src/control/basic.ts} +3 -3
- package/src/control/hover-helper.ts +10 -11
- package/src/control/index.ts +2 -0
- package/src/control/inject-keycode.ts +1 -3
- package/src/control/inject-text.ts +1 -3
- package/src/control/inject-touch.ts +16 -55
- package/src/control/rotate-device.ts +2 -7
- package/src/control/serializer.ts +50 -113
- package/src/control/set-screen-power-mode.ts +1 -3
- package/src/control/type.ts +32 -0
- package/src/control/writer.ts +85 -0
- package/src/device-message/stream.ts +32 -12
- package/src/index.ts +1 -2
- package/src/options/1_16/codec-options.ts +6 -7
- package/src/options/1_16/float-to-uint16.ts +33 -0
- package/src/options/1_16/index.ts +3 -1
- package/src/options/1_16/init.ts +80 -0
- package/src/options/1_16/message.ts +55 -0
- package/src/options/1_16/options.ts +147 -260
- package/src/options/1_16/scroll.ts +17 -18
- package/src/options/1_17.ts +66 -0
- package/src/options/1_18.ts +103 -39
- package/src/options/1_21.ts +49 -27
- package/src/options/1_22/index.ts +1 -0
- package/src/options/1_22/init.ts +19 -0
- package/src/options/1_22/options.ts +38 -45
- package/src/options/1_22/scroll.ts +3 -3
- package/src/options/1_23.ts +34 -22
- package/src/options/1_24.ts +23 -11
- package/src/options/1_25/options.ts +22 -4
- package/src/options/1_25/scroll.ts +4 -3
- package/src/options/2_0.ts +342 -0
- package/src/options/2_1.ts +35 -0
- package/src/options/codec.ts +98 -0
- package/src/options/index.ts +5 -0
- package/src/options/latest.ts +12 -0
- package/src/options/types.ts +164 -43
- package/tsconfig.build.json +9 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/bin/scrcpy-server +0 -0
- package/bin/version.d.ts +0 -1
- package/bin/version.js +0 -1
- package/esm/adb/client.d.ts +0 -41
- package/esm/adb/client.d.ts.map +0 -1
- package/esm/adb/client.js +0 -224
- package/esm/adb/client.js.map +0 -1
- package/esm/adb/connection.d.ts +0 -49
- package/esm/adb/connection.d.ts.map +0 -1
- package/esm/adb/connection.js +0 -122
- package/esm/adb/connection.js.map +0 -1
- package/esm/adb/index.d.ts +0 -4
- package/esm/adb/index.d.ts.map +0 -1
- package/esm/adb/index.js +0 -4
- package/esm/adb/index.js.map +0 -1
- package/esm/adb/options/1_16.d.ts +0 -8
- package/esm/adb/options/1_16.d.ts.map +0 -1
- package/esm/adb/options/1_16.js +0 -20
- package/esm/adb/options/1_16.js.map +0 -1
- package/esm/adb/options/1_22.d.ts +0 -8
- package/esm/adb/options/1_22.d.ts.map +0 -1
- package/esm/adb/options/1_22.js +0 -17
- package/esm/adb/options/1_22.js.map +0 -1
- package/esm/adb/options/1_26.d.ts +0 -9
- package/esm/adb/options/1_26.d.ts.map +0 -1
- package/esm/adb/options/1_26.js +0 -11
- package/esm/adb/options/1_26.js.map +0 -1
- package/esm/adb/options/2_0.d.ts +0 -8
- package/esm/adb/options/2_0.d.ts.map +0 -1
- package/esm/adb/options/2_0.js +0 -13
- package/esm/adb/options/2_0.js.map +0 -1
- package/esm/adb/options/index.d.ts +0 -4
- package/esm/adb/options/index.d.ts.map +0 -1
- package/esm/adb/options/index.js +0 -4
- package/esm/adb/options/index.js.map +0 -1
- package/esm/adb/options/types.d.ts +0 -24
- package/esm/adb/options/types.d.ts.map +0 -1
- package/esm/adb/options/types.js +0 -37
- package/esm/adb/options/types.js.map +0 -1
- package/esm/codec.d.ts +0 -34
- package/esm/codec.d.ts.map +0 -1
- package/esm/codec.js +0 -37
- package/esm/codec.js.map +0 -1
- package/esm/control/simple.d.ts +0 -5
- package/esm/control/simple.d.ts.map +0 -1
- package/esm/control/simple.js.map +0 -1
- package/esm/decoder.d.ts +0 -2
- package/esm/decoder.d.ts.map +0 -1
- package/esm/decoder.js +0 -2
- package/esm/decoder.js.map +0 -1
- package/esm/options/1.17.d.ts +0 -3
- package/esm/options/1.17.d.ts.map +0 -1
- package/esm/options/1.17.js +0 -2
- package/esm/options/1.17.js.map +0 -1
- package/esm/options/1_16/h264-configuration.d.ts +0 -49
- package/esm/options/1_16/h264-configuration.d.ts.map +0 -1
- package/esm/options/1_16/h264-configuration.js +0 -414
- package/esm/options/1_16/h264-configuration.js.map +0 -1
- package/esm/options/1_16/sps.d.ts +0 -22
- package/esm/options/1_16/sps.d.ts.map +0 -1
- package/esm/options/1_16/sps.js +0 -263
- package/esm/options/1_16/sps.js.map +0 -1
- package/esm/options/1_26.d.ts +0 -57
- package/esm/options/1_26.d.ts.map +0 -1
- package/esm/options/1_26.js +0 -67
- package/esm/options/1_26.js.map +0 -1
- package/esm/options/2.d.ts +0 -57
- package/esm/options/2.d.ts.map +0 -1
- package/esm/options/2.js +0 -67
- package/esm/options/2.js.map +0 -1
- package/scripts/fetch-server.cjs +0 -38
- package/src/adb/client.ts +0 -329
- package/src/adb/connection.ts +0 -209
- package/src/adb/index.ts +0 -3
- package/src/adb/options/1_16.ts +0 -32
- package/src/adb/options/1_22.ts +0 -26
- package/src/adb/options/index.ts +0 -3
- package/src/adb/options/types.ts +0 -75
- package/src/codec.ts +0 -35
- package/src/options/1_16/h264-configuration.ts +0 -485
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Split NAL units from an H.264/H.265 Annex B stream.
|
|
3
|
+
*
|
|
4
|
+
* The input is not modified.
|
|
5
|
+
* The returned NAL units are views of the input (no memory allocation nor copy),
|
|
6
|
+
* and still contains emulation prevention bytes.
|
|
7
|
+
*
|
|
8
|
+
* This methods returns a generator, so it can be stopped immediately
|
|
9
|
+
* after the interested NAL unit is found.
|
|
10
|
+
*/
|
|
11
|
+
export function* annexBSplitNalu(buffer: Uint8Array): Generator<Uint8Array> {
|
|
12
|
+
// -1 means we haven't found the first start code
|
|
13
|
+
let start = -1;
|
|
14
|
+
// How many `0x00`s in a row we have counted
|
|
15
|
+
let zeroCount = 0;
|
|
16
|
+
let inEmulation = false;
|
|
17
|
+
|
|
18
|
+
for (let i = 0; i < buffer.length; i += 1) {
|
|
19
|
+
const byte = buffer[i]!;
|
|
20
|
+
|
|
21
|
+
if (inEmulation) {
|
|
22
|
+
if (byte > 0x03) {
|
|
23
|
+
// `0x00000304` or larger are invalid
|
|
24
|
+
throw new Error("Invalid data");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
inEmulation = false;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (byte === 0x00) {
|
|
32
|
+
zeroCount += 1;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const prevZeroCount = zeroCount;
|
|
37
|
+
zeroCount = 0;
|
|
38
|
+
|
|
39
|
+
if (start === -1) {
|
|
40
|
+
// 0x000001 is the start code
|
|
41
|
+
// But it can be preceded by any number of zeros
|
|
42
|
+
// So 2 is the minimal
|
|
43
|
+
if (prevZeroCount >= 2 && byte === 0x01) {
|
|
44
|
+
// Found start of first NAL unit
|
|
45
|
+
start = i + 1;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Not begin with start code
|
|
50
|
+
throw new Error("Invalid data");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (prevZeroCount < 2) {
|
|
54
|
+
// zero or one `0x00`s are acceptable
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (byte === 0x01) {
|
|
59
|
+
// Found another NAL unit
|
|
60
|
+
yield buffer.subarray(start, i - prevZeroCount);
|
|
61
|
+
|
|
62
|
+
start = i + 1;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (prevZeroCount > 2) {
|
|
67
|
+
// Too much `0x00`s
|
|
68
|
+
throw new Error("Invalid data");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
switch (byte) {
|
|
72
|
+
case 0x02:
|
|
73
|
+
// Didn't find why, but 7.4.1 NAL unit semantics forbids `0x000002` appearing in NAL units
|
|
74
|
+
throw new Error("Invalid data");
|
|
75
|
+
case 0x03:
|
|
76
|
+
// `0x000003` is the "emulation_prevention_three_byte"
|
|
77
|
+
// `0x00000300`, `0x00000301`, `0x00000302` and `0x00000303` represent
|
|
78
|
+
// `0x000000`, `0x000001`, `0x000002` and `0x000003` respectively
|
|
79
|
+
inEmulation = true;
|
|
80
|
+
break;
|
|
81
|
+
default:
|
|
82
|
+
// `0x000004` or larger are as-is
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (inEmulation) {
|
|
88
|
+
throw new Error("Invalid data");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
yield buffer.subarray(start, buffer.length);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Remove emulation prevention bytes from a H.264/H.265 NAL Unit.
|
|
96
|
+
*
|
|
97
|
+
* The input is not modified.
|
|
98
|
+
* If the input doesn't contain any emulation prevention bytes,
|
|
99
|
+
* the input is returned as-is.
|
|
100
|
+
* Otherwise, a new `Uint8Array` is created and returned.
|
|
101
|
+
*/
|
|
102
|
+
export function naluRemoveEmulation(buffer: Uint8Array) {
|
|
103
|
+
// output will be created when first emulation prevention byte is found
|
|
104
|
+
let output: Uint8Array | undefined;
|
|
105
|
+
let outputOffset = 0;
|
|
106
|
+
|
|
107
|
+
let zeroCount = 0;
|
|
108
|
+
let inEmulation = false;
|
|
109
|
+
|
|
110
|
+
let i = 0;
|
|
111
|
+
scan: for (; i < buffer.length; i += 1) {
|
|
112
|
+
const byte = buffer[i]!;
|
|
113
|
+
|
|
114
|
+
if (byte === 0x00) {
|
|
115
|
+
zeroCount += 1;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Current byte is not zero
|
|
120
|
+
const prevZeroCount = zeroCount;
|
|
121
|
+
zeroCount = 0;
|
|
122
|
+
|
|
123
|
+
if (prevZeroCount < 2) {
|
|
124
|
+
// zero or one `0x00`s are acceptable
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (byte === 0x01) {
|
|
129
|
+
// Unexpected start code
|
|
130
|
+
throw new Error("Invalid data");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (prevZeroCount > 2) {
|
|
134
|
+
// Too much `0x00`s
|
|
135
|
+
throw new Error("Invalid data");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
switch (byte) {
|
|
139
|
+
case 0x02:
|
|
140
|
+
// Didn't find why, but 7.4.1 NAL unit semantics forbids `0x000002` appearing in NAL units
|
|
141
|
+
throw new Error("Invalid data");
|
|
142
|
+
case 0x03:
|
|
143
|
+
// `0x000003` is the "emulation_prevention_three_byte"
|
|
144
|
+
// `0x00000300`, `0x00000301`, `0x00000302` and `0x00000303` represent
|
|
145
|
+
// `0x000000`, `0x000001`, `0x000002` and `0x000003` respectively
|
|
146
|
+
inEmulation = true;
|
|
147
|
+
|
|
148
|
+
// Create output and copy the data before the emulation prevention byte
|
|
149
|
+
// Output size is unknown, so we use the input size as an upper bound
|
|
150
|
+
output = new Uint8Array(buffer.length - 1);
|
|
151
|
+
output.set(buffer.subarray(0, i));
|
|
152
|
+
outputOffset = i;
|
|
153
|
+
i += 1;
|
|
154
|
+
break scan;
|
|
155
|
+
default:
|
|
156
|
+
// `0x000004` or larger are as-is
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!output) {
|
|
162
|
+
return buffer;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Continue at the byte after the emulation prevention byte
|
|
166
|
+
for (; i < buffer.length; i += 1) {
|
|
167
|
+
const byte = buffer[i]!;
|
|
168
|
+
|
|
169
|
+
output[outputOffset] = byte;
|
|
170
|
+
outputOffset += 1;
|
|
171
|
+
|
|
172
|
+
if (inEmulation) {
|
|
173
|
+
if (byte > 0x03) {
|
|
174
|
+
// `0x00000304` or larger are invalid
|
|
175
|
+
throw new Error("Invalid data");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// `00000300000300` results in `0000000000` (both `0x03` are removed)
|
|
179
|
+
// which means the `0x00` after `0x03` also counts
|
|
180
|
+
if (byte === 0x00) {
|
|
181
|
+
zeroCount += 1;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
inEmulation = false;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (byte === 0x00) {
|
|
189
|
+
zeroCount += 1;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const prevZeroCount = zeroCount;
|
|
194
|
+
zeroCount = 0;
|
|
195
|
+
|
|
196
|
+
if (prevZeroCount < 2) {
|
|
197
|
+
// zero or one `0x00`s are acceptable
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (byte === 0x01) {
|
|
202
|
+
// Unexpected start code
|
|
203
|
+
throw new Error("Invalid data");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (prevZeroCount > 2) {
|
|
207
|
+
// Too much `0x00`s
|
|
208
|
+
throw new Error("Invalid data");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
switch (byte) {
|
|
212
|
+
case 0x02:
|
|
213
|
+
// Didn't find why, but 7.4.1 NAL unit semantics forbids `0x000002` appearing in NAL units
|
|
214
|
+
throw new Error("Invalid data");
|
|
215
|
+
case 0x03:
|
|
216
|
+
// `0x000003` is the "emulation_prevention_three_byte"
|
|
217
|
+
// `0x00000300`, `0x00000301`, `0x00000302` and `0x00000303` represent
|
|
218
|
+
// `0x000000`, `0x000001`, `0x000002` and `0x000003` respectively
|
|
219
|
+
inEmulation = true;
|
|
220
|
+
|
|
221
|
+
// Remove the emulation prevention byte
|
|
222
|
+
outputOffset -= 1;
|
|
223
|
+
break;
|
|
224
|
+
default:
|
|
225
|
+
// `0x000004` or larger are as-is
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return output.subarray(0, outputOffset);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export class NaluSodbBitReader {
|
|
234
|
+
readonly #nalu: Uint8Array;
|
|
235
|
+
readonly #byteLength: number;
|
|
236
|
+
readonly #stopBitIndex: number;
|
|
237
|
+
|
|
238
|
+
#zeroCount = 0;
|
|
239
|
+
#bytePosition = -1;
|
|
240
|
+
#bitPosition = -1;
|
|
241
|
+
#byte = 0;
|
|
242
|
+
|
|
243
|
+
get byteLength() {
|
|
244
|
+
return this.#byteLength;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
get stopBitIndex() {
|
|
248
|
+
return this.#stopBitIndex;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
get bytePosition() {
|
|
252
|
+
return this.#bytePosition;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
get bitPosition() {
|
|
256
|
+
return this.#bitPosition;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
get ended() {
|
|
260
|
+
return (
|
|
261
|
+
this.#bytePosition === this.#byteLength &&
|
|
262
|
+
this.#bitPosition === this.#stopBitIndex
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
constructor(nalu: Uint8Array) {
|
|
267
|
+
this.#nalu = nalu;
|
|
268
|
+
|
|
269
|
+
for (let i = nalu.length - 1; i >= 0; i -= 1) {
|
|
270
|
+
if (this.#nalu[i] === 0) {
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const byte = nalu[i]!;
|
|
275
|
+
for (let j = 0; j < 8; j += 1) {
|
|
276
|
+
if (((byte >> j) & 1) === 1) {
|
|
277
|
+
this.#byteLength = i;
|
|
278
|
+
this.#stopBitIndex = j;
|
|
279
|
+
this.#readByte();
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
throw new Error("Stop bit not found");
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
#readByte() {
|
|
289
|
+
this.#byte = this.#nalu[this.#bytePosition]!;
|
|
290
|
+
if (this.#zeroCount === 2 && this.#byte === 3) {
|
|
291
|
+
this.#zeroCount = 0;
|
|
292
|
+
this.#bytePosition += 1;
|
|
293
|
+
this.#readByte();
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (this.#byte === 0) {
|
|
298
|
+
this.#zeroCount += 1;
|
|
299
|
+
} else {
|
|
300
|
+
this.#zeroCount = 0;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
next() {
|
|
305
|
+
if (this.#bitPosition === -1) {
|
|
306
|
+
this.#bitPosition = 7;
|
|
307
|
+
this.#bytePosition += 1;
|
|
308
|
+
this.#readByte();
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (this.ended) {
|
|
312
|
+
throw new Error("Bit index out of bounds");
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const value = (this.#byte >> this.#bitPosition) & 1;
|
|
316
|
+
this.#bitPosition -= 1;
|
|
317
|
+
return value;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
read(length: number): number {
|
|
321
|
+
if (length > 32) {
|
|
322
|
+
throw new Error("Read length too large");
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
let result = 0;
|
|
326
|
+
for (let i = 0; i < length; i += 1) {
|
|
327
|
+
result = (result << 1) | this.next();
|
|
328
|
+
}
|
|
329
|
+
return result;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
skip(length: number) {
|
|
333
|
+
for (let i = 0; i < length; i += 1) {
|
|
334
|
+
this.next();
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
decodeExponentialGolombNumber(): number {
|
|
339
|
+
let length = 0;
|
|
340
|
+
while (this.next() === 0) {
|
|
341
|
+
length += 1;
|
|
342
|
+
}
|
|
343
|
+
if (length === 0) {
|
|
344
|
+
return 0;
|
|
345
|
+
}
|
|
346
|
+
return ((1 << length) | this.read(length)) - 1;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
#save() {
|
|
350
|
+
return {
|
|
351
|
+
zeroCount: this.#zeroCount,
|
|
352
|
+
bytePosition: this.#bytePosition,
|
|
353
|
+
bitPosition: this.#bitPosition,
|
|
354
|
+
byte: this.#byte,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
#restore(state: {
|
|
359
|
+
zeroCount: number;
|
|
360
|
+
bytePosition: number;
|
|
361
|
+
bitPosition: number;
|
|
362
|
+
byte: number;
|
|
363
|
+
}) {
|
|
364
|
+
this.#zeroCount = state.zeroCount;
|
|
365
|
+
this.#bytePosition = state.bytePosition;
|
|
366
|
+
this.#bitPosition = state.bitPosition;
|
|
367
|
+
this.#byte = state.byte;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
peek(length: number) {
|
|
371
|
+
const state = this.#save();
|
|
372
|
+
const result = this.read(length);
|
|
373
|
+
this.#restore(state);
|
|
374
|
+
return result;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
readBytes(length: number): Uint8Array {
|
|
378
|
+
const result = new Uint8Array(length);
|
|
379
|
+
for (let i = 0; i < length; i += 1) {
|
|
380
|
+
result[i] = this.read(8);
|
|
381
|
+
}
|
|
382
|
+
return result;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
peekBytes(length: number): Uint8Array {
|
|
386
|
+
const state = this.#save();
|
|
387
|
+
const result = this.readBytes(length);
|
|
388
|
+
this.#restore(state);
|
|
389
|
+
return result;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Struct } from "@yume-chan/struct";
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Struct } from "@yume-chan/struct";
|
|
2
|
+
|
|
3
|
+
export const BasicControlMessage = new Struct().uint8("type");
|
|
@@ -15,34 +15,33 @@ import { ScrcpyControlMessageType } from "./type.js";
|
|
|
15
15
|
* so Scrcpy server can remove the previously hovering pointer.
|
|
16
16
|
*/
|
|
17
17
|
export class ScrcpyHoverHelper {
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
private lastHoverMessage: ScrcpyInjectTouchControlMessage | undefined;
|
|
18
|
+
// There can be only one hovering pointer (either mouse or pen,
|
|
19
|
+
// touch can have multiple pointers but no hovering state).
|
|
20
|
+
#lastHoverMessage: ScrcpyInjectTouchControlMessage | undefined;
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
message: Omit<ScrcpyInjectTouchControlMessage, "type"
|
|
22
|
+
process(
|
|
23
|
+
message: Omit<ScrcpyInjectTouchControlMessage, "type">,
|
|
25
24
|
): ScrcpyInjectTouchControlMessage[] {
|
|
26
25
|
const result: ScrcpyInjectTouchControlMessage[] = [];
|
|
27
26
|
|
|
28
27
|
// A different pointer appeared,
|
|
29
28
|
// Cancel previously hovering pointer so Scrcpy server can free up the pointer ID.
|
|
30
29
|
if (
|
|
31
|
-
this
|
|
32
|
-
this
|
|
30
|
+
this.#lastHoverMessage &&
|
|
31
|
+
this.#lastHoverMessage.pointerId !== message.pointerId
|
|
33
32
|
) {
|
|
34
33
|
// TODO: Inject MotionEvent.ACTION_HOVER_EXIT
|
|
35
34
|
// From testing, it seems no App cares about this event.
|
|
36
35
|
result.push({
|
|
37
|
-
...this
|
|
36
|
+
...this.#lastHoverMessage,
|
|
38
37
|
action: AndroidMotionEventAction.Up,
|
|
39
38
|
});
|
|
40
|
-
this
|
|
39
|
+
this.#lastHoverMessage = undefined;
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
if (message.action === AndroidMotionEventAction.HoverMove) {
|
|
44
43
|
// TODO: Inject MotionEvent.ACTION_HOVER_ENTER
|
|
45
|
-
this
|
|
44
|
+
this.#lastHoverMessage = message as ScrcpyInjectTouchControlMessage;
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
(message as ScrcpyInjectTouchControlMessage).type =
|
package/src/control/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "./back-or-screen-on.js";
|
|
2
|
+
export * from "./basic.js";
|
|
2
3
|
export * from "./hover-helper.js";
|
|
3
4
|
export * from "./inject-keycode.js";
|
|
4
5
|
export * from "./inject-scroll.js";
|
|
@@ -9,3 +10,4 @@ export * from "./serializer.js";
|
|
|
9
10
|
export * from "./set-clipboard.js";
|
|
10
11
|
export * from "./set-screen-power-mode.js";
|
|
11
12
|
export * from "./type.js";
|
|
13
|
+
export * from "./writer.js";
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import Struct, { placeholder } from "@yume-chan/struct";
|
|
2
2
|
|
|
3
|
-
import { ScrcpyControlMessageType } from "./type.js";
|
|
4
|
-
|
|
5
3
|
export enum AndroidKeyEventAction {
|
|
6
4
|
Down = 0,
|
|
7
5
|
Up = 1,
|
|
@@ -207,7 +205,7 @@ export enum AndroidKeyCode {
|
|
|
207
205
|
}
|
|
208
206
|
|
|
209
207
|
export const ScrcpyInjectKeyCodeControlMessage = new Struct()
|
|
210
|
-
.uint8("type"
|
|
208
|
+
.uint8("type")
|
|
211
209
|
.uint8("action", placeholder<AndroidKeyEventAction>())
|
|
212
210
|
.uint32("keyCode")
|
|
213
211
|
.uint32("repeat")
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import Struct from "@yume-chan/struct";
|
|
2
2
|
|
|
3
|
-
import { ScrcpyControlMessageType } from "./type.js";
|
|
4
|
-
|
|
5
3
|
export const ScrcpyInjectTextControlMessage = new Struct()
|
|
6
|
-
.uint8("type"
|
|
4
|
+
.uint8("type")
|
|
7
5
|
.uint32("length")
|
|
8
6
|
.string("text", { lengthField: "length" });
|
|
9
7
|
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
NumberFieldDefinition,
|
|
3
|
-
NumberFieldType,
|
|
4
|
-
placeholder,
|
|
5
|
-
} from "@yume-chan/struct";
|
|
6
|
-
|
|
7
|
-
import { ScrcpyControlMessageType } from "./type.js";
|
|
1
|
+
import type { ScrcpyInjectTouchControlMessage2_0 } from "../options/index.js";
|
|
8
2
|
|
|
9
3
|
// https://developer.android.com/reference/android/view/MotionEvent#constants_1
|
|
10
4
|
export enum AndroidMotionEventAction {
|
|
@@ -23,56 +17,23 @@ export enum AndroidMotionEventAction {
|
|
|
23
17
|
ButtonRelease,
|
|
24
18
|
}
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
20
|
+
export enum AndroidMotionEventButton {
|
|
21
|
+
Primary = 0x01,
|
|
22
|
+
Secondary = 0x02,
|
|
23
|
+
Tertiary = 0x04,
|
|
24
|
+
Back = 0x08,
|
|
25
|
+
Forward = 0x10,
|
|
26
|
+
StylusPrimary = 0x20,
|
|
27
|
+
StylusSecondary = 0x40,
|
|
32
28
|
}
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return max;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return value;
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
31
|
+
export namespace ScrcpyPointerId {
|
|
32
|
+
export const Mouse = -1n;
|
|
33
|
+
export const Finger = -2n;
|
|
34
|
+
export const VirtualMouse = -3n;
|
|
35
|
+
export const VirtualFinger = -4n;
|
|
44
36
|
}
|
|
45
37
|
|
|
46
|
-
export const ScrcpyFloatToUint16NumberType: NumberFieldType = {
|
|
47
|
-
size: 2,
|
|
48
|
-
signed: false,
|
|
49
|
-
deserialize(array, littleEndian) {
|
|
50
|
-
const value = NumberFieldType.Uint16.deserialize(array, littleEndian);
|
|
51
|
-
// https://github.com/Genymobile/scrcpy/blob/1f138aef41de651668043b32c4effc2d4adbfc44/server/src/main/java/com/genymobile/scrcpy/Binary.java#L22
|
|
52
|
-
return value === 0xffff ? 1 : value / 0x10000;
|
|
53
|
-
},
|
|
54
|
-
serialize(dataView, offset, value, littleEndian) {
|
|
55
|
-
// https://github.com/Genymobile/scrcpy/blob/1f138aef41de651668043b32c4effc2d4adbfc44/app/src/util/binary.h#L51
|
|
56
|
-
value = clamp(value, -1, 1);
|
|
57
|
-
value = value === 1 ? 0xffff : value * 0x10000;
|
|
58
|
-
NumberFieldType.Uint16.serialize(dataView, offset, value, littleEndian);
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const ScrcpyFloatToUint16FieldDefinition = new NumberFieldDefinition(
|
|
63
|
-
ScrcpyFloatToUint16NumberType
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
export const ScrcpyInjectTouchControlMessage = new Struct()
|
|
67
|
-
.uint8("type", ScrcpyControlMessageType.InjectTouch as const)
|
|
68
|
-
.uint8("action", placeholder<AndroidMotionEventAction>())
|
|
69
|
-
.uint64("pointerId")
|
|
70
|
-
.uint32("pointerX")
|
|
71
|
-
.uint32("pointerY")
|
|
72
|
-
.uint16("screenWidth")
|
|
73
|
-
.uint16("screenHeight")
|
|
74
|
-
.field("pressure", ScrcpyFloatToUint16FieldDefinition)
|
|
75
|
-
.uint32("buttons");
|
|
76
|
-
|
|
77
38
|
export type ScrcpyInjectTouchControlMessage =
|
|
78
|
-
|
|
39
|
+
ScrcpyInjectTouchControlMessage2_0;
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { BasicControlMessage } from "./basic.js";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export const ScrcpyRotateDeviceControlMessage = new Struct().uint8(
|
|
6
|
-
"type",
|
|
7
|
-
ScrcpyControlMessageType.RotateDevice as const
|
|
8
|
-
);
|
|
3
|
+
export const ScrcpyRotateDeviceControlMessage = BasicControlMessage;
|
|
9
4
|
|
|
10
5
|
export type ScrcpyRotateDeviceControlMessage =
|
|
11
6
|
(typeof ScrcpyRotateDeviceControlMessage)["TInit"];
|