diff --git a/.vscode/settings.json b/.vscode/settings.json index 84c46192..68d7476a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,7 @@ "allowlist", "arraybuffer", "autorun", + "Bframes", "brotli", "Callout", "Cascadia", diff --git a/apps/demo/src/components/scrcpy/settings.tsx b/apps/demo/src/components/scrcpy/settings.tsx index e6515787..08a712e2 100644 --- a/apps/demo/src/components/scrcpy/settings.tsx +++ b/apps/demo/src/components/scrcpy/settings.tsx @@ -184,6 +184,7 @@ export interface H264Decoder extends Disposable { readonly renderer: HTMLElement; readonly frameRendered: number; + readonly frameSkipped: number; readonly writable: WritableStream; } diff --git a/apps/demo/src/components/scrcpy/state.tsx b/apps/demo/src/components/scrcpy/state.tsx index b93b3f1a..8535ab3d 100644 --- a/apps/demo/src/components/scrcpy/state.tsx +++ b/apps/demo/src/components/scrcpy/state.tsx @@ -67,7 +67,7 @@ export class ScrcpyPageState { decoder: H264Decoder | undefined = undefined; configuration: ScrcpyVideoStreamConfigurationPacket | undefined = undefined; fpsCounterIntervalId: any = undefined; - fps = 0; + fps = "0"; connecting = false; serverTotalSize = 0; @@ -199,11 +199,22 @@ export class ScrcpyPageState { runInAction(() => { this.decoder = decoder; - let lastFrameCount = 0; + let lastFrameRendered = 0; + let lastFrameSkipped = 0; this.fpsCounterIntervalId = setInterval( action(() => { - this.fps = decoder.frameRendered - lastFrameCount; - lastFrameCount = decoder.frameRendered; + const deltaRendered = + decoder.frameRendered - lastFrameRendered; + const deltaSkipped = + decoder.frameSkipped - lastFrameSkipped; + // prettier-ignore + this.fps = `${ + deltaRendered + }${ + deltaSkipped ? `+${deltaSkipped} skipped` : "" + }`; + lastFrameRendered = decoder.frameRendered; + lastFrameSkipped = decoder.frameSkipped; }), 1000 ); @@ -328,7 +339,7 @@ export class ScrcpyPageState { RECORD_STATE.recording = false; } - this.fps = 0; + this.fps = "0"; clearTimeout(this.fpsCounterIntervalId); this.client = undefined; diff --git a/libraries/scrcpy-decoder-tinyh264/src/index.ts b/libraries/scrcpy-decoder-tinyh264/src/index.ts index 32c9d484..7274e3a5 100644 --- a/libraries/scrcpy-decoder-tinyh264/src/index.ts +++ b/libraries/scrcpy-decoder-tinyh264/src/index.ts @@ -43,6 +43,11 @@ export class TinyH264Decoder { return this._frameRendered; } + private _frameSkipped = 0; + public get frameSkipped() { + return this._frameSkipped; + } + private _writable: WritableStream; public get writable() { return this._writable; diff --git a/libraries/scrcpy-decoder-webcodecs/src/index.ts b/libraries/scrcpy-decoder-webcodecs/src/index.ts index 8a6dbc93..c56b0a2e 100644 --- a/libraries/scrcpy-decoder-webcodecs/src/index.ts +++ b/libraries/scrcpy-decoder-webcodecs/src/index.ts @@ -29,6 +29,11 @@ export class WebCodecsDecoder { return this._frameRendered; } + private _frameSkipped = 0; + public get frameSkipped() { + return this._frameSkipped; + } + private context: CanvasRenderingContext2D; private decoder: VideoDecoder; @@ -43,6 +48,7 @@ export class WebCodecsDecoder { this.decoder = new VideoDecoder({ output: (frame) => { if (this.lastFrame) { + this._frameSkipped += 1; this.lastFrame.close(); } this.lastFrame = frame; diff --git a/libraries/scrcpy/src/options/1_16/codec-options.ts b/libraries/scrcpy/src/options/1_16/codec-options.ts index 0e47576f..66efe0b4 100644 --- a/libraries/scrcpy/src/options/1_16/codec-options.ts +++ b/libraries/scrcpy/src/options/1_16/codec-options.ts @@ -13,6 +13,7 @@ export interface CodecOptionsInit { level: AndroidCodecLevel; iFrameInterval: number; + maxBframes: number; repeatPreviousFrameAfter: number; maxPtsGapToEncoder: number; }