Loading apps/demo/package.json +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "scripts": { "postinstall": "fetch-scrcpy-server 1.22", "postinstall": "fetch-scrcpy-server 1.23", "dev": "next dev", "build": "next build", "start": "next start", Loading apps/demo/pages/scrcpy.tsx +7 −13 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ import { CommandBar, Dialog, Dropdown, ICommandBarItemProps, Icon, IconButton, I import { useId } from "@fluentui/react-hooks"; import { ADB_SYNC_MAX_PACKET_SIZE, ChunkStream, InspectStream, ReadableStream, WritableStream } from '@yume-chan/adb'; import { EventEmitter } from "@yume-chan/event"; import { AndroidKeyCode, AndroidKeyEventAction, AndroidMotionEventAction, CodecOptions, DEFAULT_SERVER_PATH, H264Decoder, H264DecoderConstructor, pushServer, ScrcpyClient, ScrcpyLogLevel, ScrcpyOptions1_22, ScrcpyScreenOrientation, TinyH264Decoder, VideoStreamPacket, WebCodecsDecoder } from "@yume-chan/scrcpy"; import { AndroidKeyCode, AndroidKeyEventAction, AndroidMotionEventAction, CodecOptions, DEFAULT_SERVER_PATH, H264Decoder, H264DecoderConstructor, pushServer, ScrcpyClient, ScrcpyLogLevel, ScrcpyOptions1_23, ScrcpyScreenOrientation, TinyH264Decoder, WebCodecsDecoder, type VideoStreamPacket } from "@yume-chan/scrcpy"; import SCRCPY_SERVER_VERSION from '@yume-chan/scrcpy/bin/version'; import { action, autorun, makeAutoObservable, observable, runInAction } from "mobx"; import { observer } from "mobx-react-lite"; Loading Loading @@ -433,12 +433,16 @@ class ScrcpyPageState { globalState.device, DEFAULT_SERVER_PATH, SCRCPY_SERVER_VERSION, new ScrcpyOptions1_22({ new ScrcpyOptions1_23({ logLevel: ScrcpyLogLevel.Debug, bitRate: 4_000_000, tunnelForward: this.tunnelForward, sendDeviceMeta: false, sendDummyByte: false, control: false, // Don't cleanup when getting encoders, // so doesn't need to push server binary again cleanup: false, }) ); if (encoders.length === 0) { Loading @@ -449,23 +453,13 @@ class ScrcpyPageState { this.encoders = encoders; }); // Run scrcpy once will delete the server file // Re-push it await new ReadableStream<Uint8Array>({ start(controller) { controller.enqueue(serverBuffer); controller.close(); }, }) .pipeTo(pushServer(globalState.device)); const factory = this.selectedDecoder.factory; const decoder = new factory(); runInAction(() => { this.decoder = decoder; }); const options = new ScrcpyOptions1_22({ const options = new ScrcpyOptions1_23({ logLevel: ScrcpyLogLevel.Debug, maxSize: this.resolution, bitRate: this.bitRate, Loading libraries/scrcpy/README.md +1 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ Scrcpy server has no backward compatibility on options input format. Currently t | 1.18~1.20 | `ScrcpyOptions1_18` | | 1.21 | `ScrcpyOptions1_21` | | 1.22 | `ScrcpyOptions1_22` | | 1.23 | `ScrcpyOptions1_23` | You must use the correct type according to the server version. Loading libraries/scrcpy/src/client.ts +3 −3 Original line number Diff line number Diff line Loading @@ -135,7 +135,7 @@ export class ScrcpyClient { adb: Adb, options: ScrcpyOptions<any>, process: AdbSubprocessProtocol, videoStream: AdbBufferedStream, videoStream: AdbSocket, controlStream: AdbSocket | undefined, ) { this._adb = adb; Loading @@ -155,8 +155,8 @@ export class ScrcpyClient { }, })); this._videoStream = options .parseVideoStream(videoStream) this._videoStream = videoStream.readable .pipeThrough(options.createVideoStreamTransformer()) .pipeThrough(new InspectStream(packet => { if (packet.type === 'configuration') { this._screenWidth = packet.data.croppedWidth; Loading libraries/scrcpy/src/connection.ts +33 −11 Original line number Diff line number Diff line import { Adb, AdbBufferedStream, AdbSocket } from "@yume-chan/adb"; import type { Adb, AdbSocket } from "@yume-chan/adb"; import type { Disposable } from "@yume-chan/event"; import type { ValueOrPromise } from "@yume-chan/struct"; import { delay } from "./utils.js"; Loading Loading @@ -29,7 +29,7 @@ export abstract class ScrcpyClientConnection implements Disposable { public initialize(): ValueOrPromise<void> { } public abstract getStreams(): ValueOrPromise<[videoSteam: AdbBufferedStream, controlStream: AdbSocket | undefined]>; public abstract getStreams(): ValueOrPromise<[videoSteam: AdbSocket, controlStream: AdbSocket | undefined]>; public dispose(): void { } } Loading @@ -50,26 +50,39 @@ export class ScrcpyClientForwardConnection extends ScrcpyClientConnection { throw new Error(`Can't connect to server after 100 retries`); } private async connectVideoStream(): Promise<AdbBufferedStream> { const socket = await this.connectAndRetry(); const stream = new AdbBufferedStream(socket); private async connectVideoStream(): Promise<AdbSocket> { const stream = await this.connectAndRetry(); if (this.options.sendDummyByte) { const reader = stream.readable.getReader(); const { done, value } = await reader.read(); // server will write a `0` to signal connection success await stream.read(1); if (done || value.byteLength !== 1 || value[0] !== 0) { throw new Error('Unexpected response from server'); } reader.releaseLock(); } return stream; } public async getStreams(): Promise<[videoSteam: AdbBufferedStream, controlStream: AdbSocket | undefined]> { public async getStreams(): Promise<[videoSteam: AdbSocket, controlStream: AdbSocket | undefined]> { const videoStream = await this.connectVideoStream(); let controlStream: AdbSocket | undefined; if (this.options.control) { controlStream = await this.connectAndRetry(); } // Server only writes device meta after control socket is connected (if enabled) if (this.options.sendDeviceMeta) { const reader = videoStream.readable.getReader(); const { done, value } = await reader.read(); // 64 bytes device name + 2 bytes video width + 2 bytes video height await videoStream.read(64 + 2 + 2); if (done || value.byteLength !== 64 + 2 + 2) { throw new Error('Unexpected response from server'); } reader.releaseLock(); } return [videoStream, controlStream]; } } Loading Loading @@ -101,16 +114,25 @@ export class ScrcpyClientReverseConnection extends ScrcpyClientConnection { return (await this.streams.read()).value!; } public async getStreams(): Promise<[videoSteam: AdbBufferedStream, controlStream: AdbSocket | undefined]> { const videoStream = new AdbBufferedStream(await this.accept()); public async getStreams(): Promise<[videoSteam: AdbSocket, controlStream: AdbSocket | undefined]> { const videoStream = await this.accept(); let controlStream: AdbSocket | undefined; if (this.options.control) { controlStream = await this.accept(); } // Server only writes device meta after control socket is connected (if enabled) if (this.options.sendDeviceMeta) { const reader = videoStream.readable.getReader(); const { done, value } = await reader.read(); // 64 bytes device name + 2 bytes video width + 2 bytes video height await videoStream.read(64 + 2 + 2); if (done || value.byteLength !== 64 + 2 + 2) { throw new Error('Unexpected response from server'); } reader.releaseLock(); } return [videoStream, controlStream]; } Loading Loading
apps/demo/package.json +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "scripts": { "postinstall": "fetch-scrcpy-server 1.22", "postinstall": "fetch-scrcpy-server 1.23", "dev": "next dev", "build": "next build", "start": "next start", Loading
apps/demo/pages/scrcpy.tsx +7 −13 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ import { CommandBar, Dialog, Dropdown, ICommandBarItemProps, Icon, IconButton, I import { useId } from "@fluentui/react-hooks"; import { ADB_SYNC_MAX_PACKET_SIZE, ChunkStream, InspectStream, ReadableStream, WritableStream } from '@yume-chan/adb'; import { EventEmitter } from "@yume-chan/event"; import { AndroidKeyCode, AndroidKeyEventAction, AndroidMotionEventAction, CodecOptions, DEFAULT_SERVER_PATH, H264Decoder, H264DecoderConstructor, pushServer, ScrcpyClient, ScrcpyLogLevel, ScrcpyOptions1_22, ScrcpyScreenOrientation, TinyH264Decoder, VideoStreamPacket, WebCodecsDecoder } from "@yume-chan/scrcpy"; import { AndroidKeyCode, AndroidKeyEventAction, AndroidMotionEventAction, CodecOptions, DEFAULT_SERVER_PATH, H264Decoder, H264DecoderConstructor, pushServer, ScrcpyClient, ScrcpyLogLevel, ScrcpyOptions1_23, ScrcpyScreenOrientation, TinyH264Decoder, WebCodecsDecoder, type VideoStreamPacket } from "@yume-chan/scrcpy"; import SCRCPY_SERVER_VERSION from '@yume-chan/scrcpy/bin/version'; import { action, autorun, makeAutoObservable, observable, runInAction } from "mobx"; import { observer } from "mobx-react-lite"; Loading Loading @@ -433,12 +433,16 @@ class ScrcpyPageState { globalState.device, DEFAULT_SERVER_PATH, SCRCPY_SERVER_VERSION, new ScrcpyOptions1_22({ new ScrcpyOptions1_23({ logLevel: ScrcpyLogLevel.Debug, bitRate: 4_000_000, tunnelForward: this.tunnelForward, sendDeviceMeta: false, sendDummyByte: false, control: false, // Don't cleanup when getting encoders, // so doesn't need to push server binary again cleanup: false, }) ); if (encoders.length === 0) { Loading @@ -449,23 +453,13 @@ class ScrcpyPageState { this.encoders = encoders; }); // Run scrcpy once will delete the server file // Re-push it await new ReadableStream<Uint8Array>({ start(controller) { controller.enqueue(serverBuffer); controller.close(); }, }) .pipeTo(pushServer(globalState.device)); const factory = this.selectedDecoder.factory; const decoder = new factory(); runInAction(() => { this.decoder = decoder; }); const options = new ScrcpyOptions1_22({ const options = new ScrcpyOptions1_23({ logLevel: ScrcpyLogLevel.Debug, maxSize: this.resolution, bitRate: this.bitRate, Loading
libraries/scrcpy/README.md +1 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ Scrcpy server has no backward compatibility on options input format. Currently t | 1.18~1.20 | `ScrcpyOptions1_18` | | 1.21 | `ScrcpyOptions1_21` | | 1.22 | `ScrcpyOptions1_22` | | 1.23 | `ScrcpyOptions1_23` | You must use the correct type according to the server version. Loading
libraries/scrcpy/src/client.ts +3 −3 Original line number Diff line number Diff line Loading @@ -135,7 +135,7 @@ export class ScrcpyClient { adb: Adb, options: ScrcpyOptions<any>, process: AdbSubprocessProtocol, videoStream: AdbBufferedStream, videoStream: AdbSocket, controlStream: AdbSocket | undefined, ) { this._adb = adb; Loading @@ -155,8 +155,8 @@ export class ScrcpyClient { }, })); this._videoStream = options .parseVideoStream(videoStream) this._videoStream = videoStream.readable .pipeThrough(options.createVideoStreamTransformer()) .pipeThrough(new InspectStream(packet => { if (packet.type === 'configuration') { this._screenWidth = packet.data.croppedWidth; Loading
libraries/scrcpy/src/connection.ts +33 −11 Original line number Diff line number Diff line import { Adb, AdbBufferedStream, AdbSocket } from "@yume-chan/adb"; import type { Adb, AdbSocket } from "@yume-chan/adb"; import type { Disposable } from "@yume-chan/event"; import type { ValueOrPromise } from "@yume-chan/struct"; import { delay } from "./utils.js"; Loading Loading @@ -29,7 +29,7 @@ export abstract class ScrcpyClientConnection implements Disposable { public initialize(): ValueOrPromise<void> { } public abstract getStreams(): ValueOrPromise<[videoSteam: AdbBufferedStream, controlStream: AdbSocket | undefined]>; public abstract getStreams(): ValueOrPromise<[videoSteam: AdbSocket, controlStream: AdbSocket | undefined]>; public dispose(): void { } } Loading @@ -50,26 +50,39 @@ export class ScrcpyClientForwardConnection extends ScrcpyClientConnection { throw new Error(`Can't connect to server after 100 retries`); } private async connectVideoStream(): Promise<AdbBufferedStream> { const socket = await this.connectAndRetry(); const stream = new AdbBufferedStream(socket); private async connectVideoStream(): Promise<AdbSocket> { const stream = await this.connectAndRetry(); if (this.options.sendDummyByte) { const reader = stream.readable.getReader(); const { done, value } = await reader.read(); // server will write a `0` to signal connection success await stream.read(1); if (done || value.byteLength !== 1 || value[0] !== 0) { throw new Error('Unexpected response from server'); } reader.releaseLock(); } return stream; } public async getStreams(): Promise<[videoSteam: AdbBufferedStream, controlStream: AdbSocket | undefined]> { public async getStreams(): Promise<[videoSteam: AdbSocket, controlStream: AdbSocket | undefined]> { const videoStream = await this.connectVideoStream(); let controlStream: AdbSocket | undefined; if (this.options.control) { controlStream = await this.connectAndRetry(); } // Server only writes device meta after control socket is connected (if enabled) if (this.options.sendDeviceMeta) { const reader = videoStream.readable.getReader(); const { done, value } = await reader.read(); // 64 bytes device name + 2 bytes video width + 2 bytes video height await videoStream.read(64 + 2 + 2); if (done || value.byteLength !== 64 + 2 + 2) { throw new Error('Unexpected response from server'); } reader.releaseLock(); } return [videoStream, controlStream]; } } Loading Loading @@ -101,16 +114,25 @@ export class ScrcpyClientReverseConnection extends ScrcpyClientConnection { return (await this.streams.read()).value!; } public async getStreams(): Promise<[videoSteam: AdbBufferedStream, controlStream: AdbSocket | undefined]> { const videoStream = new AdbBufferedStream(await this.accept()); public async getStreams(): Promise<[videoSteam: AdbSocket, controlStream: AdbSocket | undefined]> { const videoStream = await this.accept(); let controlStream: AdbSocket | undefined; if (this.options.control) { controlStream = await this.accept(); } // Server only writes device meta after control socket is connected (if enabled) if (this.options.sendDeviceMeta) { const reader = videoStream.readable.getReader(); const { done, value } = await reader.read(); // 64 bytes device name + 2 bytes video width + 2 bytes video height await videoStream.read(64 + 2 + 2); if (done || value.byteLength !== 64 + 2 + 2) { throw new Error('Unexpected response from server'); } reader.releaseLock(); } return [videoStream, controlStream]; } Loading