@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.
Files changed (278) hide show
  1. package/CHANGELOG.json +30 -0
  2. package/CHANGELOG.md +17 -1
  3. package/README.md +76 -266
  4. package/esm/codec/av1.js +2 -2
  5. package/esm/codec/av1.js.map +1 -1
  6. package/esm/codec/h264.d.ts +1 -21
  7. package/esm/codec/h264.d.ts.map +1 -1
  8. package/esm/codec/h264.js +15 -236
  9. package/esm/codec/h264.js.map +1 -1
  10. package/esm/codec/h265.d.ts +454 -0
  11. package/esm/codec/h265.d.ts.map +1 -1
  12. package/esm/codec/h265.js +1062 -2
  13. package/esm/codec/h265.js.map +1 -1
  14. package/esm/codec/index.d.ts +1 -0
  15. package/esm/codec/index.d.ts.map +1 -1
  16. package/esm/codec/index.js +1 -0
  17. package/esm/codec/index.js.map +1 -1
  18. package/esm/codec/nalu.d.ts +37 -0
  19. package/esm/codec/nalu.d.ts.map +1 -0
  20. package/esm/codec/nalu.js +323 -0
  21. package/esm/codec/nalu.js.map +1 -0
  22. package/esm/control/back-or-screen-on.d.ts +1 -1
  23. package/esm/control/back-or-screen-on.d.ts.map +1 -1
  24. package/esm/control/hover-helper.d.ts +1 -1
  25. package/esm/control/hover-helper.d.ts.map +1 -1
  26. package/esm/control/hover-helper.js +8 -9
  27. package/esm/control/hover-helper.js.map +1 -1
  28. package/esm/control/index.d.ts +2 -0
  29. package/esm/control/index.d.ts.map +1 -1
  30. package/esm/control/index.js +2 -0
  31. package/esm/control/index.js.map +1 -1
  32. package/esm/control/inject-keycode.d.ts +1 -2
  33. package/esm/control/inject-keycode.d.ts.map +1 -1
  34. package/esm/control/inject-keycode.js +4 -5
  35. package/esm/control/inject-keycode.js.map +1 -1
  36. package/esm/control/inject-text.d.ts +1 -2
  37. package/esm/control/inject-text.d.ts.map +1 -1
  38. package/esm/control/inject-text.js +1 -2
  39. package/esm/control/inject-text.js.map +1 -1
  40. package/esm/control/inject-touch.d.ts +15 -20
  41. package/esm/control/inject-touch.d.ts.map +1 -1
  42. package/esm/control/inject-touch.js +16 -43
  43. package/esm/control/inject-touch.js.map +1 -1
  44. package/esm/control/rotate-device.d.ts +2 -4
  45. package/esm/control/rotate-device.d.ts.map +1 -1
  46. package/esm/control/rotate-device.js +2 -3
  47. package/esm/control/rotate-device.js.map +1 -1
  48. package/esm/control/serializer.d.ts +11 -23
  49. package/esm/control/serializer.d.ts.map +1 -1
  50. package/esm/control/serializer.js +23 -52
  51. package/esm/control/serializer.js.map +1 -1
  52. package/esm/control/set-screen-power-mode.d.ts +1 -2
  53. package/esm/control/set-screen-power-mode.d.ts.map +1 -1
  54. package/esm/control/set-screen-power-mode.js +2 -3
  55. package/esm/control/set-screen-power-mode.js.map +1 -1
  56. package/esm/control/type.d.ts +14 -0
  57. package/esm/control/type.d.ts.map +1 -1
  58. package/esm/control/type.js +23 -1
  59. package/esm/control/type.js.map +1 -1
  60. package/esm/control/writer.d.ts +26 -0
  61. package/esm/control/writer.d.ts.map +1 -0
  62. package/esm/control/writer.js +53 -0
  63. package/esm/control/writer.js.map +1 -0
  64. package/esm/device-message/stream.d.ts.map +1 -1
  65. package/esm/device-message/stream.js +23 -8
  66. package/esm/device-message/stream.js.map +1 -1
  67. package/esm/device-message/type.js +1 -1
  68. package/esm/device-message/type.js.map +1 -1
  69. package/esm/index.d.ts +1 -2
  70. package/esm/index.d.ts.map +1 -1
  71. package/esm/index.js +1 -2
  72. package/esm/index.js.map +1 -1
  73. package/esm/options/1_16/codec-options.d.ts +2 -3
  74. package/esm/options/1_16/codec-options.d.ts.map +1 -1
  75. package/esm/options/1_16/codec-options.js.map +1 -1
  76. package/esm/options/1_16/index.d.ts +3 -1
  77. package/esm/options/1_16/index.d.ts.map +1 -1
  78. package/esm/options/1_16/index.js +3 -1
  79. package/esm/options/1_16/index.js.map +1 -1
  80. package/esm/options/1_16/init.js +2 -2
  81. package/esm/options/1_16/init.js.map +1 -1
  82. package/esm/options/1_16/options.d.ts +42 -96
  83. package/esm/options/1_16/options.d.ts.map +1 -1
  84. package/esm/options/1_16/options.js +104 -142
  85. package/esm/options/1_16/options.js.map +1 -1
  86. package/esm/options/1_16/scroll.d.ts +2 -4
  87. package/esm/options/1_16/scroll.d.ts.map +1 -1
  88. package/esm/options/1_16/scroll.js +13 -14
  89. package/esm/options/1_16/scroll.js.map +1 -1
  90. package/esm/options/1_17.d.ts +1 -0
  91. package/esm/options/1_17.d.ts.map +1 -1
  92. package/esm/options/1_17.js +8 -3
  93. package/esm/options/1_17.js.map +1 -1
  94. package/esm/options/1_18.d.ts +49 -11
  95. package/esm/options/1_18.d.ts.map +1 -1
  96. package/esm/options/1_18.js +64 -32
  97. package/esm/options/1_18.js.map +1 -1
  98. package/esm/options/1_21.d.ts +26 -7
  99. package/esm/options/1_21.d.ts.map +1 -1
  100. package/esm/options/1_21.js +34 -20
  101. package/esm/options/1_21.js.map +1 -1
  102. package/esm/options/1_22/index.d.ts +1 -0
  103. package/esm/options/1_22/index.d.ts.map +1 -1
  104. package/esm/options/1_22/index.js +1 -0
  105. package/esm/options/1_22/index.js.map +1 -1
  106. package/esm/options/1_22/options.d.ts +32 -26
  107. package/esm/options/1_22/options.d.ts.map +1 -1
  108. package/esm/options/1_22/options.js +26 -16
  109. package/esm/options/1_22/options.js.map +1 -1
  110. package/esm/options/1_22/scroll.d.ts +1 -1
  111. package/esm/options/1_22/scroll.d.ts.map +1 -1
  112. package/esm/options/1_22/scroll.js +1 -1
  113. package/esm/options/1_22/scroll.js.map +1 -1
  114. package/esm/options/1_23.d.ts +32 -8
  115. package/esm/options/1_23.d.ts.map +1 -1
  116. package/esm/options/1_23.js +23 -14
  117. package/esm/options/1_23.js.map +1 -1
  118. package/esm/options/1_24.d.ts +29 -4
  119. package/esm/options/1_24.d.ts.map +1 -1
  120. package/esm/options/1_24.js +16 -7
  121. package/esm/options/1_24.js.map +1 -1
  122. package/esm/options/1_25/options.d.ts +6 -2
  123. package/esm/options/1_25/options.d.ts.map +1 -1
  124. package/esm/options/1_25/options.js +16 -2
  125. package/esm/options/1_25/options.js.map +1 -1
  126. package/esm/options/1_25/scroll.d.ts.map +1 -1
  127. package/esm/options/1_25/scroll.js +2 -1
  128. package/esm/options/1_25/scroll.js.map +1 -1
  129. package/esm/options/2_0.d.ts +12 -8
  130. package/esm/options/2_0.d.ts.map +1 -1
  131. package/esm/options/2_0.js +82 -15
  132. package/esm/options/2_0.js.map +1 -1
  133. package/esm/options/2_1.d.ts +48 -0
  134. package/esm/options/2_1.d.ts.map +1 -0
  135. package/esm/options/2_1.js +23 -0
  136. package/esm/options/2_1.js.map +1 -0
  137. package/esm/options/codec.d.ts +4 -4
  138. package/esm/options/codec.d.ts.map +1 -1
  139. package/esm/options/codec.js +5 -6
  140. package/esm/options/codec.js.map +1 -1
  141. package/esm/options/index.d.ts +5 -0
  142. package/esm/options/index.d.ts.map +1 -1
  143. package/esm/options/index.js +5 -0
  144. package/esm/options/index.js.map +1 -1
  145. package/esm/options/latest.d.ts +4 -5
  146. package/esm/options/latest.d.ts.map +1 -1
  147. package/esm/options/latest.js +2 -3
  148. package/esm/options/latest.js.map +1 -1
  149. package/esm/options/types.d.ts +74 -33
  150. package/esm/options/types.d.ts.map +1 -1
  151. package/esm/options/types.js +62 -0
  152. package/esm/options/types.js.map +1 -1
  153. package/package.json +9 -19
  154. package/src/codec/av1.ts +33 -0
  155. package/src/codec/h264.ts +317 -0
  156. package/src/codec/h265.ts +1375 -0
  157. package/src/codec/index.ts +4 -0
  158. package/src/codec/nalu.ts +391 -0
  159. package/src/control/back-or-screen-on.ts +1 -1
  160. package/{esm/control/simple.js → src/control/basic.ts} +3 -3
  161. package/src/control/hover-helper.ts +10 -11
  162. package/src/control/index.ts +2 -0
  163. package/src/control/inject-keycode.ts +1 -3
  164. package/src/control/inject-text.ts +1 -3
  165. package/src/control/inject-touch.ts +16 -55
  166. package/src/control/rotate-device.ts +2 -7
  167. package/src/control/serializer.ts +50 -113
  168. package/src/control/set-screen-power-mode.ts +1 -3
  169. package/src/control/type.ts +32 -0
  170. package/src/control/writer.ts +85 -0
  171. package/src/device-message/stream.ts +32 -12
  172. package/src/index.ts +1 -2
  173. package/src/options/1_16/codec-options.ts +6 -7
  174. package/src/options/1_16/float-to-uint16.ts +33 -0
  175. package/src/options/1_16/index.ts +3 -1
  176. package/src/options/1_16/init.ts +80 -0
  177. package/src/options/1_16/message.ts +55 -0
  178. package/src/options/1_16/options.ts +147 -260
  179. package/src/options/1_16/scroll.ts +17 -18
  180. package/src/options/1_17.ts +66 -0
  181. package/src/options/1_18.ts +103 -39
  182. package/src/options/1_21.ts +49 -27
  183. package/src/options/1_22/index.ts +1 -0
  184. package/src/options/1_22/init.ts +19 -0
  185. package/src/options/1_22/options.ts +38 -45
  186. package/src/options/1_22/scroll.ts +3 -3
  187. package/src/options/1_23.ts +34 -22
  188. package/src/options/1_24.ts +23 -11
  189. package/src/options/1_25/options.ts +22 -4
  190. package/src/options/1_25/scroll.ts +4 -3
  191. package/src/options/2_0.ts +342 -0
  192. package/src/options/2_1.ts +35 -0
  193. package/src/options/codec.ts +98 -0
  194. package/src/options/index.ts +5 -0
  195. package/src/options/latest.ts +12 -0
  196. package/src/options/types.ts +164 -43
  197. package/tsconfig.build.json +9 -1
  198. package/tsconfig.build.tsbuildinfo +1 -1
  199. package/bin/scrcpy-server +0 -0
  200. package/bin/version.d.ts +0 -1
  201. package/bin/version.js +0 -1
  202. package/esm/adb/client.d.ts +0 -41
  203. package/esm/adb/client.d.ts.map +0 -1
  204. package/esm/adb/client.js +0 -224
  205. package/esm/adb/client.js.map +0 -1
  206. package/esm/adb/connection.d.ts +0 -49
  207. package/esm/adb/connection.d.ts.map +0 -1
  208. package/esm/adb/connection.js +0 -122
  209. package/esm/adb/connection.js.map +0 -1
  210. package/esm/adb/index.d.ts +0 -4
  211. package/esm/adb/index.d.ts.map +0 -1
  212. package/esm/adb/index.js +0 -4
  213. package/esm/adb/index.js.map +0 -1
  214. package/esm/adb/options/1_16.d.ts +0 -8
  215. package/esm/adb/options/1_16.d.ts.map +0 -1
  216. package/esm/adb/options/1_16.js +0 -20
  217. package/esm/adb/options/1_16.js.map +0 -1
  218. package/esm/adb/options/1_22.d.ts +0 -8
  219. package/esm/adb/options/1_22.d.ts.map +0 -1
  220. package/esm/adb/options/1_22.js +0 -17
  221. package/esm/adb/options/1_22.js.map +0 -1
  222. package/esm/adb/options/1_26.d.ts +0 -9
  223. package/esm/adb/options/1_26.d.ts.map +0 -1
  224. package/esm/adb/options/1_26.js +0 -11
  225. package/esm/adb/options/1_26.js.map +0 -1
  226. package/esm/adb/options/2_0.d.ts +0 -8
  227. package/esm/adb/options/2_0.d.ts.map +0 -1
  228. package/esm/adb/options/2_0.js +0 -13
  229. package/esm/adb/options/2_0.js.map +0 -1
  230. package/esm/adb/options/index.d.ts +0 -4
  231. package/esm/adb/options/index.d.ts.map +0 -1
  232. package/esm/adb/options/index.js +0 -4
  233. package/esm/adb/options/index.js.map +0 -1
  234. package/esm/adb/options/types.d.ts +0 -24
  235. package/esm/adb/options/types.d.ts.map +0 -1
  236. package/esm/adb/options/types.js +0 -37
  237. package/esm/adb/options/types.js.map +0 -1
  238. package/esm/codec.d.ts +0 -34
  239. package/esm/codec.d.ts.map +0 -1
  240. package/esm/codec.js +0 -37
  241. package/esm/codec.js.map +0 -1
  242. package/esm/control/simple.d.ts +0 -5
  243. package/esm/control/simple.d.ts.map +0 -1
  244. package/esm/control/simple.js.map +0 -1
  245. package/esm/decoder.d.ts +0 -2
  246. package/esm/decoder.d.ts.map +0 -1
  247. package/esm/decoder.js +0 -2
  248. package/esm/decoder.js.map +0 -1
  249. package/esm/options/1.17.d.ts +0 -3
  250. package/esm/options/1.17.d.ts.map +0 -1
  251. package/esm/options/1.17.js +0 -2
  252. package/esm/options/1.17.js.map +0 -1
  253. package/esm/options/1_16/h264-configuration.d.ts +0 -49
  254. package/esm/options/1_16/h264-configuration.d.ts.map +0 -1
  255. package/esm/options/1_16/h264-configuration.js +0 -414
  256. package/esm/options/1_16/h264-configuration.js.map +0 -1
  257. package/esm/options/1_16/sps.d.ts +0 -22
  258. package/esm/options/1_16/sps.d.ts.map +0 -1
  259. package/esm/options/1_16/sps.js +0 -263
  260. package/esm/options/1_16/sps.js.map +0 -1
  261. package/esm/options/1_26.d.ts +0 -57
  262. package/esm/options/1_26.d.ts.map +0 -1
  263. package/esm/options/1_26.js +0 -67
  264. package/esm/options/1_26.js.map +0 -1
  265. package/esm/options/2.d.ts +0 -57
  266. package/esm/options/2.d.ts.map +0 -1
  267. package/esm/options/2.js +0 -67
  268. package/esm/options/2.js.map +0 -1
  269. package/scripts/fetch-server.cjs +0 -38
  270. package/src/adb/client.ts +0 -329
  271. package/src/adb/connection.ts +0 -209
  272. package/src/adb/index.ts +0 -3
  273. package/src/adb/options/1_16.ts +0 -32
  274. package/src/adb/options/1_22.ts +0 -26
  275. package/src/adb/options/index.ts +0 -3
  276. package/src/adb/options/types.ts +0 -75
  277. package/src/codec.ts +0 -35
  278. package/src/options/1_16/h264-configuration.ts +0 -485
@@ -0,0 +1,342 @@
1
+ import type { ReadableStream } from "@yume-chan/stream-extra";
2
+ import {
3
+ BufferedReadableStream,
4
+ PushReadableStream,
5
+ } from "@yume-chan/stream-extra";
6
+ import type { ValueOrPromise } from "@yume-chan/struct";
7
+ import Struct, { NumberFieldType, placeholder } from "@yume-chan/struct";
8
+
9
+ import type {
10
+ AndroidMotionEventAction,
11
+ ScrcpyInjectTouchControlMessage,
12
+ } from "../control/index.js";
13
+
14
+ import {
15
+ CodecOptions,
16
+ ScrcpyFloatToUint16FieldDefinition,
17
+ ScrcpyOptions1_16,
18
+ } from "./1_16/index.js";
19
+ import { ScrcpyOptions1_21 } from "./1_21.js";
20
+ import type { ScrcpyOptionsInit1_24 } from "./1_24.js";
21
+ import { ScrcpyOptions1_24 } from "./1_24.js";
22
+ import { ScrcpyOptions1_25 } from "./1_25/index.js";
23
+ import type { ScrcpyAudioStreamMetadata, ScrcpyVideoStream } from "./codec.js";
24
+ import { ScrcpyAudioCodec, ScrcpyVideoCodecId } from "./codec.js";
25
+ import type {
26
+ ScrcpyDisplay,
27
+ ScrcpyEncoder,
28
+ ScrcpyOptionValue,
29
+ } from "./types.js";
30
+ import { ScrcpyOptionsBase } from "./types.js";
31
+
32
+ export const ScrcpyInjectTouchControlMessage2_0 = new Struct()
33
+ .uint8("type")
34
+ .uint8("action", placeholder<AndroidMotionEventAction>())
35
+ .uint64("pointerId")
36
+ .uint32("pointerX")
37
+ .uint32("pointerY")
38
+ .uint16("screenWidth")
39
+ .uint16("screenHeight")
40
+ .field("pressure", ScrcpyFloatToUint16FieldDefinition)
41
+ .uint32("actionButton")
42
+ .uint32("buttons");
43
+
44
+ export type ScrcpyInjectTouchControlMessage2_0 =
45
+ (typeof ScrcpyInjectTouchControlMessage2_0)["TInit"];
46
+
47
+ export class ScrcpyInstanceId implements ScrcpyOptionValue {
48
+ static readonly NONE = new ScrcpyInstanceId(-1);
49
+
50
+ static random(): ScrcpyInstanceId {
51
+ // A random 31-bit unsigned integer
52
+ return new ScrcpyInstanceId((Math.random() * 0x80000000) | 0);
53
+ }
54
+
55
+ value: number;
56
+
57
+ constructor(value: number) {
58
+ this.value = value;
59
+ }
60
+
61
+ toOptionValue(): string | undefined {
62
+ if (this.value < 0) {
63
+ return undefined;
64
+ }
65
+ return this.value.toString(16);
66
+ }
67
+ }
68
+
69
+ export interface ScrcpyOptionsInit2_0
70
+ extends Omit<
71
+ ScrcpyOptionsInit1_24,
72
+ "bitRate" | "codecOptions" | "encoderName"
73
+ > {
74
+ scid?: ScrcpyInstanceId;
75
+
76
+ videoCodec?: "h264" | "h265" | "av1";
77
+ videoBitRate?: number;
78
+ videoCodecOptions?: CodecOptions;
79
+ videoEncoder?: string;
80
+
81
+ audio?: boolean;
82
+ audioCodec?: "opus" | "aac" | "raw";
83
+ audioBitRate?: number;
84
+ audioCodecOptions?: CodecOptions;
85
+ audioEncoder?: string;
86
+
87
+ listEncoders?: boolean;
88
+ listDisplays?: boolean;
89
+ sendCodecMeta?: boolean;
90
+ }
91
+
92
+ function omit<T extends object, K extends keyof T>(
93
+ obj: T,
94
+ keys: K[],
95
+ ): Omit<T, K> {
96
+ const result: Record<PropertyKey, unknown> = {};
97
+ for (const key in obj) {
98
+ if (!keys.includes(key as keyof T as K)) {
99
+ result[key] = obj[key];
100
+ }
101
+ }
102
+ return result as Omit<T, K>;
103
+ }
104
+
105
+ export class ScrcpyOptions2_0 extends ScrcpyOptionsBase<
106
+ ScrcpyOptionsInit2_0,
107
+ ScrcpyOptions1_25
108
+ > {
109
+ static readonly DEFAULTS = {
110
+ ...omit(ScrcpyOptions1_24.DEFAULTS, [
111
+ "bitRate",
112
+ "codecOptions",
113
+ "encoderName",
114
+ ]),
115
+ scid: ScrcpyInstanceId.NONE,
116
+
117
+ videoCodec: "h264",
118
+ videoBitRate: 8000000,
119
+ videoCodecOptions: new CodecOptions(),
120
+ videoEncoder: "",
121
+
122
+ audio: true,
123
+ audioCodec: "opus",
124
+ audioBitRate: 128000,
125
+ audioCodecOptions: new CodecOptions(),
126
+ audioEncoder: "",
127
+
128
+ listEncoders: false,
129
+ listDisplays: false,
130
+ sendCodecMeta: true,
131
+ } as const satisfies Required<ScrcpyOptionsInit2_0>;
132
+
133
+ override get defaults(): Required<ScrcpyOptionsInit2_0> {
134
+ return ScrcpyOptions2_0.DEFAULTS;
135
+ }
136
+
137
+ constructor(init: ScrcpyOptionsInit2_0) {
138
+ super(new ScrcpyOptions1_25(init), {
139
+ ...ScrcpyOptions2_0.DEFAULTS,
140
+ ...init,
141
+ });
142
+ }
143
+
144
+ override serialize(): string[] {
145
+ return ScrcpyOptions1_21.serialize(this.value, this.defaults);
146
+ }
147
+
148
+ override setListEncoders(): void {
149
+ this.value.listEncoders = true;
150
+ }
151
+
152
+ override setListDisplays(): void {
153
+ this.value.listDisplays = true;
154
+ }
155
+
156
+ override parseEncoder(line: string): ScrcpyEncoder | undefined {
157
+ let match = line.match(
158
+ /\s+--video-codec=(.*)\s+--video-encoder='(.*)'/,
159
+ );
160
+ if (match) {
161
+ return {
162
+ type: "video",
163
+ codec: match[1]!,
164
+ name: match[2]!,
165
+ };
166
+ }
167
+
168
+ match = line.match(/\s+--audio-codec=(.*)\s+--audio-encoder='(.*)'/);
169
+ if (match) {
170
+ return {
171
+ type: "audio",
172
+ codec: match[1]!,
173
+ name: match[2]!,
174
+ };
175
+ }
176
+
177
+ return undefined;
178
+ }
179
+
180
+ override parseDisplay(line: string): ScrcpyDisplay | undefined {
181
+ const match = line.match(/\s+--display=(\d+)\s+\((.*?)\)/);
182
+ if (match) {
183
+ const display: ScrcpyDisplay = {
184
+ id: Number.parseInt(match[1]!, 10),
185
+ };
186
+ if (match[2] !== "size unknown") {
187
+ display.resolution = match[2]!;
188
+ }
189
+ return display;
190
+ }
191
+ return undefined;
192
+ }
193
+
194
+ override parseVideoStreamMetadata(
195
+ stream: ReadableStream<Uint8Array>,
196
+ ): ValueOrPromise<ScrcpyVideoStream> {
197
+ const { sendDeviceMeta, sendCodecMeta } = this.value;
198
+ if (!sendDeviceMeta && !sendCodecMeta) {
199
+ let codec: ScrcpyVideoCodecId;
200
+ switch (this.value.videoCodec) {
201
+ case "h264":
202
+ codec = ScrcpyVideoCodecId.H264;
203
+ break;
204
+ case "h265":
205
+ codec = ScrcpyVideoCodecId.H265;
206
+ break;
207
+ case "av1":
208
+ codec = ScrcpyVideoCodecId.AV1;
209
+ break;
210
+ }
211
+ return { stream, metadata: { codec } };
212
+ }
213
+
214
+ return (async () => {
215
+ const buffered = new BufferedReadableStream(stream);
216
+
217
+ // `sendDeviceMeta` now only contains device name,
218
+ // can't use `super.parseVideoStreamMetadata` here
219
+ let deviceName: string | undefined;
220
+ if (sendDeviceMeta) {
221
+ deviceName = await ScrcpyOptions1_16.parseCString(buffered, 64);
222
+ }
223
+
224
+ let codec: ScrcpyVideoCodecId;
225
+ let width: number | undefined;
226
+ let height: number | undefined;
227
+ if (sendCodecMeta) {
228
+ codec = await ScrcpyOptions1_16.parseUint32BE(buffered);
229
+ width = await ScrcpyOptions1_16.parseUint32BE(buffered);
230
+ height = await ScrcpyOptions1_16.parseUint32BE(buffered);
231
+ } else {
232
+ switch (this.value.videoCodec) {
233
+ case "h264":
234
+ codec = ScrcpyVideoCodecId.H264;
235
+ break;
236
+ case "h265":
237
+ codec = ScrcpyVideoCodecId.H265;
238
+ break;
239
+ case "av1":
240
+ codec = ScrcpyVideoCodecId.AV1;
241
+ break;
242
+ }
243
+ }
244
+
245
+ return {
246
+ stream: buffered.release(),
247
+ metadata: { deviceName, codec, width, height },
248
+ };
249
+ })();
250
+ }
251
+
252
+ override parseAudioStreamMetadata(
253
+ stream: ReadableStream<Uint8Array>,
254
+ ): ValueOrPromise<ScrcpyAudioStreamMetadata> {
255
+ return (async (): Promise<ScrcpyAudioStreamMetadata> => {
256
+ const buffered = new BufferedReadableStream(stream);
257
+ const buffer = await buffered.readExactly(
258
+ NumberFieldType.Uint32.size,
259
+ );
260
+
261
+ const codecMetadataValue = NumberFieldType.Uint32.deserialize(
262
+ buffer,
263
+ false,
264
+ );
265
+ // Server will send `0x00_00_00_00` and `0x00_00_00_01` even if `sendCodecMeta` is false
266
+ switch (codecMetadataValue) {
267
+ case 0x00_00_00_00:
268
+ return {
269
+ type: "disabled",
270
+ };
271
+ case 0x00_00_00_01:
272
+ return {
273
+ type: "errored",
274
+ };
275
+ }
276
+
277
+ if (this.value.sendCodecMeta) {
278
+ let codec: ScrcpyAudioCodec;
279
+ switch (codecMetadataValue) {
280
+ case ScrcpyAudioCodec.OPUS.metadataValue:
281
+ codec = ScrcpyAudioCodec.OPUS;
282
+ break;
283
+ case ScrcpyAudioCodec.AAC.metadataValue:
284
+ codec = ScrcpyAudioCodec.AAC;
285
+ break;
286
+ case ScrcpyAudioCodec.RAW.metadataValue:
287
+ codec = ScrcpyAudioCodec.RAW;
288
+ break;
289
+ default:
290
+ throw new Error(
291
+ `Unknown audio codec metadata value: ${codecMetadataValue}`,
292
+ );
293
+ }
294
+ return {
295
+ type: "success",
296
+ codec,
297
+ stream: buffered.release(),
298
+ };
299
+ }
300
+
301
+ // Infer codec from `audioCodec` option
302
+ let codec: ScrcpyAudioCodec;
303
+ switch (this.value.audioCodec) {
304
+ case "opus":
305
+ codec = ScrcpyAudioCodec.OPUS;
306
+ break;
307
+ case "aac":
308
+ codec = ScrcpyAudioCodec.AAC;
309
+ break;
310
+ case "raw":
311
+ codec = ScrcpyAudioCodec.RAW;
312
+ break;
313
+ }
314
+ return {
315
+ type: "success",
316
+ codec,
317
+ stream: new PushReadableStream<Uint8Array>(
318
+ async (controller) => {
319
+ // Put the first 4 bytes back
320
+ await controller.enqueue(buffer);
321
+
322
+ const stream = buffered.release();
323
+ const reader = stream.getReader();
324
+ while (true) {
325
+ const { done, value } = await reader.read();
326
+ if (done) {
327
+ break;
328
+ }
329
+ await controller.enqueue(value);
330
+ }
331
+ },
332
+ ),
333
+ };
334
+ })();
335
+ }
336
+
337
+ override serializeInjectTouchControlMessage(
338
+ message: ScrcpyInjectTouchControlMessage,
339
+ ): Uint8Array {
340
+ return ScrcpyInjectTouchControlMessage2_0.serialize(message);
341
+ }
342
+ }
@@ -0,0 +1,35 @@
1
+ import { ScrcpyOptions1_21 } from "./1_21.js";
2
+ import type { ScrcpyOptionsInit2_0 } from "./2_0.js";
3
+ import { ScrcpyOptions2_0 } from "./2_0.js";
4
+ import { ScrcpyOptionsBase } from "./types.js";
5
+
6
+ export interface ScrcpyOptionsInit2_1 extends ScrcpyOptionsInit2_0 {
7
+ video?: boolean;
8
+ audioSource?: "output" | "mic";
9
+ }
10
+
11
+ export class ScrcpyOptions2_1 extends ScrcpyOptionsBase<
12
+ ScrcpyOptionsInit2_1,
13
+ ScrcpyOptions2_0
14
+ > {
15
+ static readonly DEFAULTS = {
16
+ ...ScrcpyOptions2_0.DEFAULTS,
17
+ video: true,
18
+ audioSource: "output",
19
+ } as const satisfies Required<ScrcpyOptionsInit2_1>;
20
+
21
+ override get defaults(): Required<ScrcpyOptionsInit2_1> {
22
+ return ScrcpyOptions2_1.DEFAULTS;
23
+ }
24
+
25
+ constructor(init: ScrcpyOptionsInit2_1) {
26
+ super(new ScrcpyOptions2_0(init), {
27
+ ...ScrcpyOptions2_1.DEFAULTS,
28
+ ...init,
29
+ });
30
+ }
31
+
32
+ override serialize(): string[] {
33
+ return ScrcpyOptions1_21.serialize(this.value, this.defaults);
34
+ }
35
+ }
@@ -0,0 +1,98 @@
1
+ import type { ReadableStream } from "@yume-chan/stream-extra";
2
+
3
+ import type { ScrcpyOptionValue } from "./types.js";
4
+
5
+ export enum ScrcpyVideoCodecId {
6
+ H264 = 0x68_32_36_34,
7
+ H265 = 0x68_32_36_35,
8
+ AV1 = 0x00_61_76_31,
9
+ }
10
+
11
+ export interface ScrcpyVideoStreamMetadata {
12
+ deviceName?: string | undefined;
13
+ width?: number | undefined;
14
+ height?: number | undefined;
15
+ codec: ScrcpyVideoCodecId;
16
+ }
17
+
18
+ export interface ScrcpyVideoStream {
19
+ readonly stream: ReadableStream<Uint8Array>;
20
+ readonly metadata: ScrcpyVideoStreamMetadata;
21
+ }
22
+
23
+ export class ScrcpyAudioCodec implements ScrcpyOptionValue {
24
+ static readonly OPUS = new ScrcpyAudioCodec(
25
+ "opus",
26
+ 0x6f_70_75_73,
27
+ "audio/opus",
28
+ "opus",
29
+ );
30
+ static readonly AAC = new ScrcpyAudioCodec(
31
+ "aac",
32
+ 0x00_61_61_63,
33
+ "audio/aac",
34
+ "mp4a.66",
35
+ );
36
+ static readonly RAW = new ScrcpyAudioCodec(
37
+ "raw",
38
+ 0x00_72_61_77,
39
+ "audio/raw",
40
+ "1",
41
+ );
42
+
43
+ readonly optionValue: string;
44
+ readonly metadataValue: number;
45
+ readonly mimeType: string;
46
+ readonly webCodecId: string;
47
+
48
+ constructor(
49
+ optionValue: string,
50
+ metadataValue: number,
51
+ mimeType: string,
52
+ webCodecId: string,
53
+ ) {
54
+ this.optionValue = optionValue;
55
+ this.metadataValue = metadataValue;
56
+ this.mimeType = mimeType;
57
+ this.webCodecId = webCodecId;
58
+ }
59
+
60
+ toOptionValue(): string {
61
+ return this.optionValue;
62
+ }
63
+ }
64
+
65
+ export interface ScrcpyAudioStreamDisabledMetadata {
66
+ readonly type: "disabled";
67
+ }
68
+
69
+ export interface ScrcpyAudioStreamErroredMetadata {
70
+ readonly type: "errored";
71
+ }
72
+
73
+ export interface ScrcpyAudioStreamSuccessMetadata {
74
+ readonly type: "success";
75
+ readonly codec: ScrcpyAudioCodec;
76
+ readonly stream: ReadableStream<Uint8Array>;
77
+ }
78
+
79
+ export type ScrcpyAudioStreamMetadata =
80
+ | ScrcpyAudioStreamDisabledMetadata
81
+ | ScrcpyAudioStreamErroredMetadata
82
+ | ScrcpyAudioStreamSuccessMetadata;
83
+
84
+ export interface ScrcpyMediaStreamConfigurationPacket {
85
+ type: "configuration";
86
+ data: Uint8Array;
87
+ }
88
+
89
+ export interface ScrcpyMediaStreamDataPacket {
90
+ type: "data";
91
+ keyframe?: boolean;
92
+ pts?: bigint;
93
+ data: Uint8Array;
94
+ }
95
+
96
+ export type ScrcpyMediaStreamPacket =
97
+ | ScrcpyMediaStreamConfigurationPacket
98
+ | ScrcpyMediaStreamDataPacket;
@@ -1,8 +1,13 @@
1
1
  export * from "./1_16/index.js";
2
+ export * from "./1_17.js";
2
3
  export * from "./1_18.js";
3
4
  export * from "./1_21.js";
4
5
  export * from "./1_22/index.js";
5
6
  export * from "./1_23.js";
6
7
  export * from "./1_24.js";
7
8
  export * from "./1_25/index.js";
9
+ export * from "./2_0.js";
10
+ export * from "./2_1.js";
11
+ export * from "./codec.js";
12
+ export * from "./latest.js";
8
13
  export * from "./types.js";
@@ -0,0 +1,12 @@
1
+ import { ScrcpyLogLevel1_18, ScrcpyVideoOrientation1_18 } from "./1_18.js";
2
+ import type { ScrcpyOptionsInit2_1 } from "./2_1.js";
3
+ import { ScrcpyOptions2_1 } from "./2_1.js";
4
+
5
+ export const ScrcpyLogLevel = ScrcpyLogLevel1_18;
6
+ export type ScrcpyLogLevel = ScrcpyLogLevel1_18;
7
+
8
+ export const ScrcpyVideoOrientation = ScrcpyVideoOrientation1_18;
9
+ export type ScrcpyVideoOrientation = ScrcpyVideoOrientation1_18;
10
+
11
+ export type ScrcpyOptionsInitLatest = ScrcpyOptionsInit2_1;
12
+ export class ScrcpyOptionsLatest extends ScrcpyOptions2_1 {}