@yume-chan/scrcpy-decoder-webcodecs 2.1.0 → 2.5.3
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.md +6 -0
- package/README.md +3 -0
- package/esm/video/codec/av1.d.ts +2 -2
- package/esm/video/codec/av1.d.ts.map +1 -1
- package/esm/video/codec/av1.js +34 -7
- package/esm/video/codec/av1.js.map +1 -1
- package/esm/video/codec/h264.d.ts +3 -2
- package/esm/video/codec/h264.d.ts.map +1 -1
- package/esm/video/codec/h264.js +6 -5
- package/esm/video/codec/h264.js.map +1 -1
- package/esm/video/codec/h265.d.ts +3 -2
- package/esm/video/codec/h265.d.ts.map +1 -1
- package/esm/video/codec/h265.js +6 -5
- package/esm/video/codec/h265.js.map +1 -1
- package/esm/video/codec/h26x.d.ts +1 -1
- package/esm/video/codec/h26x.d.ts.map +1 -1
- package/esm/video/codec/h26x.js +54 -16
- package/esm/video/codec/h26x.js.map +1 -1
- package/esm/video/codec/type.d.ts +4 -1
- package/esm/video/codec/type.d.ts.map +1 -1
- package/esm/video/decoder.d.ts +4 -3
- package/esm/video/decoder.d.ts.map +1 -1
- package/esm/video/decoder.js +10 -8
- package/esm/video/decoder.js.map +1 -1
- package/package.json +5 -5
- package/src/video/codec/av1.ts +40 -7
- package/src/video/codec/h264.ts +9 -5
- package/src/video/codec/h265.ts +9 -5
- package/src/video/codec/h26x.ts +74 -18
- package/src/video/codec/type.ts +5 -0
- package/src/video/decoder.ts +18 -9
- package/tsconfig.build.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
<a href="https://tangoadb.dev/discord">
|
|
25
25
|
<img alt="Discord" src="https://img.shields.io/discord/1120215514732564502?logo=discord&logoColor=%23ffffff&label=Discord">
|
|
26
26
|
</a>
|
|
27
|
+
<a href="https://tangoadb.dev/wechat">
|
|
28
|
+
<img alt="WeChat Group" src="https://img.shields.io/badge/WeChat-Group-%2307C160?logo=wechat&logoColor=white">
|
|
29
|
+
</a>
|
|
27
30
|
</p>
|
|
28
31
|
|
|
29
32
|
This package is part of [Tango ADB](https://github.com/yume-chan/ya-webadb). Generally you need multiple packages to build a complete ADB client that can run on Web browsers and Node.js. Read the documentation for more information.
|
package/esm/video/codec/av1.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ScrcpyMediaStreamPacket } from "@yume-chan/scrcpy";
|
|
2
|
-
import type { CodecDecoder } from "./type.js";
|
|
2
|
+
import type { CodecDecoder, CodecDecoderOptions } from "./type.js";
|
|
3
3
|
export declare class Av1Codec implements CodecDecoder {
|
|
4
4
|
#private;
|
|
5
|
-
constructor(decoder: VideoDecoder, updateSize: (width: number, height: number) => void);
|
|
5
|
+
constructor(decoder: VideoDecoder, updateSize: (width: number, height: number) => void, options?: CodecDecoderOptions);
|
|
6
6
|
decode(packet: ScrcpyMediaStreamPacket): void;
|
|
7
7
|
}
|
|
8
8
|
//# sourceMappingURL=av1.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"av1.d.ts","sourceRoot":"","sources":["../../../src/video/codec/av1.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAGjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"av1.d.ts","sourceRoot":"","sources":["../../../src/video/codec/av1.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAGjE,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGnE,qBAAa,QAAS,YAAW,YAAY;;gBASrC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,mBAAmB;IA6EjC,MAAM,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI;CAuChD"}
|
package/esm/video/codec/av1.js
CHANGED
|
@@ -3,11 +3,15 @@ import { decimalTwoDigits } from "./utils.js";
|
|
|
3
3
|
export class Av1Codec {
|
|
4
4
|
#decoder;
|
|
5
5
|
#updateSize;
|
|
6
|
-
|
|
6
|
+
#options;
|
|
7
|
+
#config;
|
|
8
|
+
#configured = false;
|
|
9
|
+
constructor(decoder, updateSize, options) {
|
|
7
10
|
this.#decoder = decoder;
|
|
8
11
|
this.#updateSize = updateSize;
|
|
12
|
+
this.#options = options;
|
|
9
13
|
}
|
|
10
|
-
#
|
|
14
|
+
#parseConfig(data) {
|
|
11
15
|
const parser = new Av1(data);
|
|
12
16
|
const sequenceHeader = parser.searchSequenceHeaderObu();
|
|
13
17
|
if (!sequenceHeader) {
|
|
@@ -50,19 +54,42 @@ export class Av1Codec {
|
|
|
50
54
|
decimalTwoDigits(matrixCoefficients),
|
|
51
55
|
colorRange ? "1" : "0",
|
|
52
56
|
].join(".");
|
|
53
|
-
this.#
|
|
57
|
+
this.#config = {
|
|
54
58
|
codec,
|
|
59
|
+
hardwareAcceleration: this.#options?.hardwareAcceleration ?? "no-preference",
|
|
55
60
|
optimizeForLatency: true,
|
|
56
|
-
}
|
|
61
|
+
};
|
|
62
|
+
this.#configured = false;
|
|
57
63
|
}
|
|
58
64
|
decode(packet) {
|
|
59
65
|
if (packet.type === "configuration") {
|
|
60
66
|
return;
|
|
61
67
|
}
|
|
62
|
-
this.#
|
|
68
|
+
this.#parseConfig(packet.data);
|
|
69
|
+
if (!this.#config) {
|
|
70
|
+
throw new Error("Decoder not configured");
|
|
71
|
+
}
|
|
72
|
+
if (packet.keyframe) {
|
|
73
|
+
if (this.#decoder.decodeQueueSize) {
|
|
74
|
+
// If the device is too slow to decode all frames,
|
|
75
|
+
// discard queued frames when next keyframe arrives.
|
|
76
|
+
// (can only do this for keyframes because decoding must start from a keyframe)
|
|
77
|
+
// This limits the maximum latency to 1 keyframe interval
|
|
78
|
+
// (60 frames by default).
|
|
79
|
+
this.#decoder.reset();
|
|
80
|
+
// `reset` also resets the decoder configuration
|
|
81
|
+
// so we need to re-configure it again.
|
|
82
|
+
this.#decoder.configure(this.#config);
|
|
83
|
+
this.#configured = true;
|
|
84
|
+
}
|
|
85
|
+
else if (!this.#configured) {
|
|
86
|
+
this.#decoder.configure(this.#config);
|
|
87
|
+
this.#configured = true;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
63
90
|
this.#decoder.decode(new EncodedVideoChunk({
|
|
64
|
-
//
|
|
65
|
-
type: packet.keyframe
|
|
91
|
+
// AV1 requires Scrcpy 2.0 where `keyframe` flag must be set
|
|
92
|
+
type: packet.keyframe ? "key" : "delta",
|
|
66
93
|
timestamp: 0,
|
|
67
94
|
data: packet.data,
|
|
68
95
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"av1.js","sourceRoot":"","sources":["../../../src/video/codec/av1.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAGxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,OAAO,QAAQ;IACjB,QAAQ,CAAe;IACvB,WAAW,CAA0C;
|
|
1
|
+
{"version":3,"file":"av1.js","sourceRoot":"","sources":["../../../src/video/codec/av1.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { H26xDecoder } from "./h26x.js";
|
|
2
|
+
import type { CodecDecoderOptions } from "./type.js";
|
|
2
3
|
export declare class H264Decoder extends H26xDecoder {
|
|
3
4
|
#private;
|
|
4
|
-
constructor(decoder: VideoDecoder, updateSize: (width: number, height: number) => void);
|
|
5
|
-
configure(data: Uint8Array):
|
|
5
|
+
constructor(decoder: VideoDecoder, updateSize: (width: number, height: number) => void, options?: CodecDecoderOptions);
|
|
6
|
+
configure(data: Uint8Array): VideoDecoderConfig;
|
|
6
7
|
}
|
|
7
8
|
//# sourceMappingURL=h264.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"h264.d.ts","sourceRoot":"","sources":["../../../src/video/codec/h264.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"h264.d.ts","sourceRoot":"","sources":["../../../src/video/codec/h264.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGrD,qBAAa,WAAY,SAAQ,WAAW;;gBAKpC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,mBAAmB;IAOxB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,kBAAkB;CAyB3D"}
|
package/esm/video/codec/h264.js
CHANGED
|
@@ -2,12 +2,12 @@ import { h264ParseConfiguration } from "@yume-chan/scrcpy";
|
|
|
2
2
|
import { H26xDecoder } from "./h26x.js";
|
|
3
3
|
import { hexTwoDigits } from "./utils.js";
|
|
4
4
|
export class H264Decoder extends H26xDecoder {
|
|
5
|
-
#decoder;
|
|
6
5
|
#updateSize;
|
|
7
|
-
|
|
6
|
+
#options;
|
|
7
|
+
constructor(decoder, updateSize, options) {
|
|
8
8
|
super(decoder);
|
|
9
|
-
this.#decoder = decoder;
|
|
10
9
|
this.#updateSize = updateSize;
|
|
10
|
+
this.#options = options;
|
|
11
11
|
}
|
|
12
12
|
configure(data) {
|
|
13
13
|
const { profileIndex, constraintSet, levelIndex, croppedWidth, croppedHeight, } = h264ParseConfiguration(data);
|
|
@@ -18,10 +18,11 @@ export class H264Decoder extends H26xDecoder {
|
|
|
18
18
|
hexTwoDigits(profileIndex) +
|
|
19
19
|
hexTwoDigits(constraintSet) +
|
|
20
20
|
hexTwoDigits(levelIndex);
|
|
21
|
-
|
|
21
|
+
return {
|
|
22
22
|
codec: codec,
|
|
23
|
+
hardwareAcceleration: this.#options?.hardwareAcceleration ?? "no-preference",
|
|
23
24
|
optimizeForLatency: true,
|
|
24
|
-
}
|
|
25
|
+
};
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
//# sourceMappingURL=h264.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"h264.js","sourceRoot":"","sources":["../../../src/video/codec/h264.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"h264.js","sourceRoot":"","sources":["../../../src/video/codec/h264.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,OAAO,WAAY,SAAQ,WAAW;IACxC,WAAW,CAA0C;IACrD,QAAQ,CAAkC;IAE1C,YACI,OAAqB,EACrB,UAAmD,EACnD,OAA6B;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAC9B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC5B,CAAC;IAEQ,SAAS,CAAC,IAAgB;QAC/B,MAAM,EACF,YAAY,EACZ,aAAa,EACb,UAAU,EACV,YAAY,EACZ,aAAa,GAChB,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAEjC,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QAE9C,qDAAqD;QACrD,wCAAwC;QACxC,MAAM,KAAK,GACP,OAAO;YACP,YAAY,CAAC,YAAY,CAAC;YAC1B,YAAY,CAAC,aAAa,CAAC;YAC3B,YAAY,CAAC,UAAU,CAAC,CAAC;QAC7B,OAAO;YACH,KAAK,EAAE,KAAK;YACZ,oBAAoB,EAChB,IAAI,CAAC,QAAQ,EAAE,oBAAoB,IAAI,eAAe;YAC1D,kBAAkB,EAAE,IAAI;SAC3B,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { H26xDecoder } from "./h26x.js";
|
|
2
|
+
import type { CodecDecoderOptions } from "./type.js";
|
|
2
3
|
export declare class H265Decoder extends H26xDecoder {
|
|
3
4
|
#private;
|
|
4
|
-
constructor(decoder: VideoDecoder, updateSize: (width: number, height: number) => void);
|
|
5
|
-
configure(data: Uint8Array):
|
|
5
|
+
constructor(decoder: VideoDecoder, updateSize: (width: number, height: number) => void, options?: CodecDecoderOptions);
|
|
6
|
+
configure(data: Uint8Array): VideoDecoderConfig;
|
|
6
7
|
}
|
|
7
8
|
//# sourceMappingURL=h265.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"h265.d.ts","sourceRoot":"","sources":["../../../src/video/codec/h265.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"h265.d.ts","sourceRoot":"","sources":["../../../src/video/codec/h265.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGrD,qBAAa,WAAY,SAAQ,WAAW;;gBAKpC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,mBAAmB;IAOxB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,kBAAkB;CAgC3D"}
|
package/esm/video/codec/h265.js
CHANGED
|
@@ -3,12 +3,12 @@ import { h265ParseConfiguration } from "@yume-chan/scrcpy";
|
|
|
3
3
|
import { H26xDecoder } from "./h26x.js";
|
|
4
4
|
import { hexDigits } from "./utils.js";
|
|
5
5
|
export class H265Decoder extends H26xDecoder {
|
|
6
|
-
#decoder;
|
|
7
6
|
#updateSize;
|
|
8
|
-
|
|
7
|
+
#options;
|
|
8
|
+
constructor(decoder, updateSize, options) {
|
|
9
9
|
super(decoder);
|
|
10
|
-
this.#decoder = decoder;
|
|
11
10
|
this.#updateSize = updateSize;
|
|
11
|
+
this.#options = options;
|
|
12
12
|
}
|
|
13
13
|
configure(data) {
|
|
14
14
|
const { generalProfileSpace, generalProfileIndex, generalProfileCompatibilitySet, generalTierFlag, generalLevelIndex, generalConstraintSet, croppedWidth, croppedHeight, } = h265ParseConfiguration(data);
|
|
@@ -21,13 +21,14 @@ export class H265Decoder extends H26xDecoder {
|
|
|
21
21
|
(generalTierFlag ? "H" : "L") + generalLevelIndex.toString(),
|
|
22
22
|
...Array.from(generalConstraintSet, hexDigits),
|
|
23
23
|
].join(".");
|
|
24
|
-
|
|
24
|
+
return {
|
|
25
25
|
codec,
|
|
26
26
|
// Microsoft Edge requires explicit size to work
|
|
27
27
|
codedWidth: croppedWidth,
|
|
28
28
|
codedHeight: croppedHeight,
|
|
29
|
+
hardwareAcceleration: this.#options?.hardwareAcceleration ?? "no-preference",
|
|
29
30
|
optimizeForLatency: true,
|
|
30
|
-
}
|
|
31
|
+
};
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
//# sourceMappingURL=h265.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"h265.js","sourceRoot":"","sources":["../../../src/video/codec/h265.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"h265.js","sourceRoot":"","sources":["../../../src/video/codec/h265.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,OAAO,WAAY,SAAQ,WAAW;IACxC,WAAW,CAA0C;IACrD,QAAQ,CAAkC;IAE1C,YACI,OAAqB,EACrB,UAAmD,EACnD,OAA6B;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAC9B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC5B,CAAC;IAEQ,SAAS,CAAC,IAAgB;QAC/B,MAAM,EACF,mBAAmB,EACnB,mBAAmB,EACnB,8BAA8B,EAC9B,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,YAAY,EACZ,aAAa,GAChB,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAEjC,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QAE9C,MAAM,KAAK,GAAG;YACV,MAAM;YACN,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,mBAAmB,CAAE;gBACrC,mBAAmB,CAAC,QAAQ,EAAE;YAClC,SAAS,CAAC,qBAAqB,CAAC,8BAA8B,EAAE,CAAC,CAAC,CAAC;YACnE,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,QAAQ,EAAE;YAC5D,GAAG,KAAK,CAAC,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC;SACjD,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,OAAO;YACH,KAAK;YACL,gDAAgD;YAChD,UAAU,EAAE,YAAY;YACxB,WAAW,EAAE,aAAa;YAC1B,oBAAoB,EAChB,IAAI,CAAC,QAAQ,EAAE,oBAAoB,IAAI,eAAe;YAC1D,kBAAkB,EAAE,IAAI;SAC3B,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -3,7 +3,7 @@ import type { CodecDecoder } from "./type.js";
|
|
|
3
3
|
export declare abstract class H26xDecoder implements CodecDecoder {
|
|
4
4
|
#private;
|
|
5
5
|
constructor(decoder: VideoDecoder);
|
|
6
|
-
abstract configure(data: Uint8Array):
|
|
6
|
+
abstract configure(data: Uint8Array): VideoDecoderConfig;
|
|
7
7
|
decode(packet: ScrcpyMediaStreamPacket): void;
|
|
8
8
|
}
|
|
9
9
|
//# sourceMappingURL=h26x.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"h26x.d.ts","sourceRoot":"","sources":["../../../src/video/codec/h26x.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"h26x.d.ts","sourceRoot":"","sources":["../../../src/video/codec/h26x.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAER,uBAAuB,EAC1B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,8BAAsB,WAAY,YAAW,YAAY;;gBAMzC,OAAO,EAAE,YAAY;IAIjC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,kBAAkB;IA2BxD,MAAM,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI;CAwDhD"}
|
package/esm/video/codec/h26x.js
CHANGED
|
@@ -1,34 +1,72 @@
|
|
|
1
1
|
export class H26xDecoder {
|
|
2
|
-
#config;
|
|
3
2
|
#decoder;
|
|
3
|
+
#config;
|
|
4
|
+
#configured = false;
|
|
4
5
|
constructor(decoder) {
|
|
5
6
|
this.#decoder = decoder;
|
|
6
7
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
this.configure(packet.data);
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
8
|
+
#configureAndDecodeFirstKeyframe(config, packet) {
|
|
9
|
+
this.#decoder.configure(config);
|
|
10
|
+
this.#configured = true;
|
|
13
11
|
// For H.264 and H.265, when the stream is in Annex B format
|
|
14
12
|
// (which Scrcpy uses, as Android MediaCodec produces),
|
|
15
13
|
// configuration data needs to be combined with the first frame data.
|
|
16
14
|
// https://www.w3.org/TR/webcodecs-avc-codec-registration/#encodedvideochunk-type
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
const { raw } = config;
|
|
16
|
+
const data = new Uint8Array(raw.length + packet.data.length);
|
|
17
|
+
data.set(raw, 0);
|
|
18
|
+
data.set(packet.data, raw.length);
|
|
19
|
+
this.#decoder.decode(new EncodedVideoChunk({
|
|
20
|
+
type: "key",
|
|
21
|
+
timestamp: 0,
|
|
22
|
+
data,
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
decode(packet) {
|
|
26
|
+
if (packet.type === "configuration") {
|
|
27
|
+
this.#config = {
|
|
28
|
+
...this.configure(packet.data),
|
|
29
|
+
raw: packet.data,
|
|
30
|
+
};
|
|
31
|
+
this.#configured = false;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!this.#config) {
|
|
35
|
+
throw new Error("Decoder not configured");
|
|
23
36
|
}
|
|
24
|
-
|
|
25
|
-
|
|
37
|
+
if (packet.keyframe) {
|
|
38
|
+
if (this.#decoder.decodeQueueSize) {
|
|
39
|
+
// If the device is too slow to decode all frames,
|
|
40
|
+
// discard queued frames when next keyframe arrives.
|
|
41
|
+
// (can only do this for keyframes because decoding must start from a keyframe)
|
|
42
|
+
// This limits the maximum latency to 1 keyframe interval
|
|
43
|
+
// (60 frames by default).
|
|
44
|
+
this.#decoder.reset();
|
|
45
|
+
// `reset` also resets the decoder configuration
|
|
46
|
+
// so we need to re-configure it again.
|
|
47
|
+
this.#configureAndDecodeFirstKeyframe(this.#config, packet);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (!this.#configured) {
|
|
51
|
+
this.#configureAndDecodeFirstKeyframe(this.#config, packet);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!this.#configured) {
|
|
56
|
+
if (packet.keyframe === undefined) {
|
|
57
|
+
// Scrcpy <1.23 doesn't send `keyframe` flag
|
|
58
|
+
// Infer the first frame after configuration as keyframe
|
|
59
|
+
// (`VideoDecoder` will throw error if it's not)
|
|
60
|
+
this.#configureAndDecodeFirstKeyframe(this.#config, packet);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
throw new Error("Expect a keyframe but got a delta frame");
|
|
26
64
|
}
|
|
27
65
|
this.#decoder.decode(new EncodedVideoChunk({
|
|
28
66
|
// Treat `undefined` as `key`, otherwise won't decode.
|
|
29
67
|
type: packet.keyframe === false ? "delta" : "key",
|
|
30
68
|
timestamp: 0,
|
|
31
|
-
data,
|
|
69
|
+
data: packet.data,
|
|
32
70
|
}));
|
|
33
71
|
}
|
|
34
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"h26x.js","sourceRoot":"","sources":["../../../src/video/codec/h26x.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"h26x.js","sourceRoot":"","sources":["../../../src/video/codec/h26x.ts"],"names":[],"mappings":"AAOA,MAAM,OAAgB,WAAW;IAC7B,QAAQ,CAAe;IAEvB,OAAO,CAAyD;IAChE,WAAW,GAAG,KAAK,CAAC;IAEpB,YAAY,OAAqB;QAC7B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC5B,CAAC;IAID,gCAAgC,CAC5B,MAAgD,EAChD,MAAmC;QAEnC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAExB,4DAA4D;QAC5D,uDAAuD;QACvD,qEAAqE;QACrE,iFAAiF;QACjF,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACjB,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAElC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAChB,IAAI,iBAAiB,CAAC;YAClB,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,CAAC;YACZ,IAAI;SACP,CAAC,CACL,CAAC;IACN,CAAC;IAED,MAAM,CAAC,MAA+B;QAClC,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YAClC,IAAI,CAAC,OAAO,GAAG;gBACX,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;gBAC9B,GAAG,EAAE,MAAM,CAAC,IAAI;aACnB,CAAC;YACF,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,OAAO;QACX,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;gBAChC,kDAAkD;gBAClD,oDAAoD;gBACpD,+EAA+E;gBAC/E,yDAAyD;gBACzD,0BAA0B;gBAC1B,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAEtB,gDAAgD;gBAChD,uCAAuC;gBACvC,IAAI,CAAC,gCAAgC,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC5D,OAAO;YACX,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBACpB,IAAI,CAAC,gCAAgC,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC5D,OAAO;YACX,CAAC;QACL,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACpB,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAChC,4CAA4C;gBAC5C,wDAAwD;gBACxD,gDAAgD;gBAChD,IAAI,CAAC,gCAAgC,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC5D,OAAO;YACX,CAAC;YAED,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,MAAM,CAChB,IAAI,iBAAiB,CAAC;YAClB,sDAAsD;YACtD,IAAI,EAAE,MAAM,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;YACjD,SAAS,EAAE,CAAC;YACZ,IAAI,EAAE,MAAM,CAAC,IAAI;SACpB,CAAC,CACL,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -2,7 +2,10 @@ import type { ScrcpyMediaStreamPacket } from "@yume-chan/scrcpy";
|
|
|
2
2
|
export interface CodecDecoder {
|
|
3
3
|
decode(packet: ScrcpyMediaStreamPacket): void;
|
|
4
4
|
}
|
|
5
|
+
export interface CodecDecoderOptions {
|
|
6
|
+
hardwareAcceleration?: HardwareAcceleration | undefined;
|
|
7
|
+
}
|
|
5
8
|
export interface CodecDecoderConstructor {
|
|
6
|
-
new (decoder: VideoDecoder, updateSize: (width: number, height: number) => void): CodecDecoder;
|
|
9
|
+
new (decoder: VideoDecoder, updateSize: (width: number, height: number) => void, options?: CodecDecoderOptions): CodecDecoder;
|
|
7
10
|
}
|
|
8
11
|
//# sourceMappingURL=type.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../../src/video/codec/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAEjE,MAAM,WAAW,YAAY;IACzB,MAAM,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI,CAAC;CACjD;AAED,MAAM,WAAW,uBAAuB;IACpC,KACI,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../../src/video/codec/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAEjE,MAAM,WAAW,YAAY;IACzB,MAAM,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI,CAAC;CACjD;AAED,MAAM,WAAW,mBAAmB;IAChC,oBAAoB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC3D;AAED,MAAM,WAAW,uBAAuB;IACpC,KACI,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,mBAAmB,GAC9B,YAAY,CAAC;CACnB"}
|
package/esm/video/decoder.d.ts
CHANGED
|
@@ -2,14 +2,15 @@ import type { ScrcpyMediaStreamPacket } from "@yume-chan/scrcpy";
|
|
|
2
2
|
import { ScrcpyVideoCodecId } from "@yume-chan/scrcpy";
|
|
3
3
|
import type { ScrcpyVideoDecoder, ScrcpyVideoDecoderCapability } from "@yume-chan/scrcpy-decoder-tinyh264";
|
|
4
4
|
import { WritableStream } from "@yume-chan/stream-extra";
|
|
5
|
+
import type { CodecDecoderOptions } from "./codec/type.js";
|
|
5
6
|
import type { VideoFrameRenderer } from "./render/index.js";
|
|
6
7
|
export declare class WebCodecsVideoDecoder implements ScrcpyVideoDecoder {
|
|
7
8
|
#private;
|
|
8
9
|
static get isSupported(): boolean;
|
|
9
10
|
static readonly capabilities: Record<string, ScrcpyVideoDecoderCapability>;
|
|
10
11
|
get codec(): ScrcpyVideoCodecId;
|
|
11
|
-
get writable(): WritableStream<ScrcpyMediaStreamPacket>;
|
|
12
12
|
get renderer(): VideoFrameRenderer;
|
|
13
|
+
get writable(): WritableStream<ScrcpyMediaStreamPacket>;
|
|
13
14
|
get framesRendered(): number;
|
|
14
15
|
get framesSkipped(): number;
|
|
15
16
|
get sizeChanged(): import("@yume-chan/event").Event<{
|
|
@@ -21,12 +22,12 @@ export declare class WebCodecsVideoDecoder implements ScrcpyVideoDecoder {
|
|
|
21
22
|
/**
|
|
22
23
|
* Create a new WebCodecs video decoder.
|
|
23
24
|
*/
|
|
24
|
-
constructor({ codec, renderer }: WebCodecsVideoDecoder.Options);
|
|
25
|
+
constructor({ codec, renderer, ...options }: WebCodecsVideoDecoder.Options);
|
|
25
26
|
snapshot(): Promise<Blob | undefined>;
|
|
26
27
|
dispose(): void;
|
|
27
28
|
}
|
|
28
29
|
export declare namespace WebCodecsVideoDecoder {
|
|
29
|
-
interface Options {
|
|
30
|
+
interface Options extends CodecDecoderOptions {
|
|
30
31
|
/**
|
|
31
32
|
* The video codec to decode
|
|
32
33
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../src/video/decoder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EACR,kBAAkB,EAClB,4BAA4B,EAC/B,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../src/video/decoder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EACR,kBAAkB,EAClB,4BAA4B,EAC/B,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,KAAK,EAAgB,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAO5D,qBAAa,qBAAsB,YAAW,kBAAkB;;IAC5D,MAAM,KAAK,WAAW,YAErB;IAED,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAKpE;IAGN,IAAI,KAAK,uBAER;IAGD,IAAI,QAAQ,uBAEX;IAOD,IAAI,QAAQ,4CAEX;IAOD,IAAI,cAAc,WAEjB;IAGD,IAAI,aAAa,WAEhB;IAGD,IAAI,WAAW;eADgC,MAAM;gBAAU,MAAM;gBAGpE;IAGD,IAAI,KAAK,WAER;IAGD,IAAI,MAAM,WAET;IAUD;;OAEG;gBACS,EACR,KAAK,EACL,QAAQ,EACR,GAAG,OAAO,EACb,EAAE,qBAAqB,CAAC,OAAO;IA6H1B,QAAQ;IAYd,OAAO;CAQV;AAED,yBAAiB,qBAAqB,CAAC;IACnC,UAAiB,OAAQ,SAAQ,mBAAmB;QAChD;;WAEG;QACH,KAAK,EAAE,kBAAkB,CAAC;QAE1B,QAAQ,EAAE,kBAAkB,CAAC;KAChC;CACJ"}
|
package/esm/video/decoder.js
CHANGED
|
@@ -20,6 +20,11 @@ export class WebCodecsVideoDecoder {
|
|
|
20
20
|
get codec() {
|
|
21
21
|
return this.#codec;
|
|
22
22
|
}
|
|
23
|
+
#renderer;
|
|
24
|
+
get renderer() {
|
|
25
|
+
return this.#renderer;
|
|
26
|
+
}
|
|
27
|
+
#options;
|
|
23
28
|
#codecDecoder;
|
|
24
29
|
#writable;
|
|
25
30
|
get writable() {
|
|
@@ -27,10 +32,6 @@ export class WebCodecsVideoDecoder {
|
|
|
27
32
|
}
|
|
28
33
|
#error;
|
|
29
34
|
#controller;
|
|
30
|
-
#renderer;
|
|
31
|
-
get renderer() {
|
|
32
|
-
return this.#renderer;
|
|
33
|
-
}
|
|
34
35
|
#framesDraw = 0;
|
|
35
36
|
#framesPresented = 0;
|
|
36
37
|
get framesRendered() {
|
|
@@ -60,9 +61,10 @@ export class WebCodecsVideoDecoder {
|
|
|
60
61
|
/**
|
|
61
62
|
* Create a new WebCodecs video decoder.
|
|
62
63
|
*/
|
|
63
|
-
constructor({ codec, renderer }) {
|
|
64
|
+
constructor({ codec, renderer, ...options }) {
|
|
64
65
|
this.#codec = codec;
|
|
65
66
|
this.#renderer = renderer;
|
|
67
|
+
this.#options = options;
|
|
66
68
|
this.#decoder = new VideoDecoder({
|
|
67
69
|
output: (frame) => {
|
|
68
70
|
this.#captureFrame?.close();
|
|
@@ -84,13 +86,13 @@ export class WebCodecsVideoDecoder {
|
|
|
84
86
|
});
|
|
85
87
|
switch (this.#codec) {
|
|
86
88
|
case ScrcpyVideoCodecId.H264:
|
|
87
|
-
this.#codecDecoder = new H264Decoder(this.#decoder, this.#updateSize);
|
|
89
|
+
this.#codecDecoder = new H264Decoder(this.#decoder, this.#updateSize, this.#options);
|
|
88
90
|
break;
|
|
89
91
|
case ScrcpyVideoCodecId.H265:
|
|
90
|
-
this.#codecDecoder = new H265Decoder(this.#decoder, this.#updateSize);
|
|
92
|
+
this.#codecDecoder = new H265Decoder(this.#decoder, this.#updateSize, this.#options);
|
|
91
93
|
break;
|
|
92
94
|
case ScrcpyVideoCodecId.AV1:
|
|
93
|
-
this.#codecDecoder = new Av1Codec(this.#decoder, this.#updateSize);
|
|
95
|
+
this.#codecDecoder = new Av1Codec(this.#decoder, this.#updateSize, this.#options);
|
|
94
96
|
break;
|
|
95
97
|
default:
|
|
96
98
|
throw new Error(`Unsupported codec: ${this.#codec}`);
|
package/esm/video/decoder.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decoder.js","sourceRoot":"","sources":["../../src/video/decoder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAMvD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEtE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,sBAAsB;AACxB,eAAe;AACf,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,kBAAkB,EAAE,EAAE,CAAC,CAAC,CAAC;AAEhD,MAAM,OAAO,qBAAqB;IAC9B,MAAM,KAAK,WAAW;QAClB,OAAO,OAAO,UAAU,CAAC,YAAY,KAAK,WAAW,CAAC;IAC1D,CAAC;IAED,MAAM,CAAU,YAAY,GACxB;QACI,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,EAAE;QACR,GAAG,EAAE,EAAE;KACV,CAAC;IAEN,MAAM,CAAqB;IAC3B,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,
|
|
1
|
+
{"version":3,"file":"decoder.js","sourceRoot":"","sources":["../../src/video/decoder.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yume-chan/scrcpy-decoder-webcodecs",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.3",
|
|
4
4
|
"description": "Raw H.264 stream decoder and renderer using WebCodecs API (requires modern browser).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adb",
|
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@yume-chan/async": "^4.1.3",
|
|
32
32
|
"@yume-chan/event": "^2.0.0",
|
|
33
|
+
"@yume-chan/scrcpy": "^2.3.0",
|
|
33
34
|
"@yume-chan/no-data-view": "^2.0.0",
|
|
34
|
-
"@yume-chan/scrcpy": "^2.1.0",
|
|
35
35
|
"@yume-chan/scrcpy-decoder-tinyh264": "^2.1.0",
|
|
36
|
-
"@yume-chan/stream-extra": "^2.
|
|
36
|
+
"@yume-chan/stream-extra": "^2.5.3"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"prettier": "^3.
|
|
40
|
-
"typescript": "^5.
|
|
39
|
+
"prettier": "^3.6.2",
|
|
40
|
+
"typescript": "^5.9.2",
|
|
41
41
|
"@yume-chan/eslint-config": "^1.0.0",
|
|
42
42
|
"@yume-chan/tsconfig": "^1.0.0"
|
|
43
43
|
},
|
package/src/video/codec/av1.ts
CHANGED
|
@@ -1,22 +1,28 @@
|
|
|
1
1
|
import type { ScrcpyMediaStreamPacket } from "@yume-chan/scrcpy";
|
|
2
2
|
import { Av1 } from "@yume-chan/scrcpy";
|
|
3
3
|
|
|
4
|
-
import type { CodecDecoder } from "./type.js";
|
|
4
|
+
import type { CodecDecoder, CodecDecoderOptions } from "./type.js";
|
|
5
5
|
import { decimalTwoDigits } from "./utils.js";
|
|
6
6
|
|
|
7
7
|
export class Av1Codec implements CodecDecoder {
|
|
8
8
|
#decoder: VideoDecoder;
|
|
9
9
|
#updateSize: (width: number, height: number) => void;
|
|
10
|
+
#options: CodecDecoderOptions | undefined;
|
|
11
|
+
|
|
12
|
+
#config: VideoDecoderConfig | undefined;
|
|
13
|
+
#configured = false;
|
|
10
14
|
|
|
11
15
|
constructor(
|
|
12
16
|
decoder: VideoDecoder,
|
|
13
17
|
updateSize: (width: number, height: number) => void,
|
|
18
|
+
options?: CodecDecoderOptions,
|
|
14
19
|
) {
|
|
15
20
|
this.#decoder = decoder;
|
|
16
21
|
this.#updateSize = updateSize;
|
|
22
|
+
this.#options = options;
|
|
17
23
|
}
|
|
18
24
|
|
|
19
|
-
#
|
|
25
|
+
#parseConfig(data: Uint8Array) {
|
|
20
26
|
const parser = new Av1(data);
|
|
21
27
|
const sequenceHeader = parser.searchSequenceHeaderObu();
|
|
22
28
|
|
|
@@ -77,10 +83,13 @@ export class Av1Codec implements CodecDecoder {
|
|
|
77
83
|
decimalTwoDigits(matrixCoefficients),
|
|
78
84
|
colorRange ? "1" : "0",
|
|
79
85
|
].join(".");
|
|
80
|
-
this.#
|
|
86
|
+
this.#config = {
|
|
81
87
|
codec,
|
|
88
|
+
hardwareAcceleration:
|
|
89
|
+
this.#options?.hardwareAcceleration ?? "no-preference",
|
|
82
90
|
optimizeForLatency: true,
|
|
83
|
-
}
|
|
91
|
+
};
|
|
92
|
+
this.#configured = false;
|
|
84
93
|
}
|
|
85
94
|
|
|
86
95
|
decode(packet: ScrcpyMediaStreamPacket): void {
|
|
@@ -88,11 +97,35 @@ export class Av1Codec implements CodecDecoder {
|
|
|
88
97
|
return;
|
|
89
98
|
}
|
|
90
99
|
|
|
91
|
-
this.#
|
|
100
|
+
this.#parseConfig(packet.data);
|
|
101
|
+
|
|
102
|
+
if (!this.#config) {
|
|
103
|
+
throw new Error("Decoder not configured");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (packet.keyframe) {
|
|
107
|
+
if (this.#decoder.decodeQueueSize) {
|
|
108
|
+
// If the device is too slow to decode all frames,
|
|
109
|
+
// discard queued frames when next keyframe arrives.
|
|
110
|
+
// (can only do this for keyframes because decoding must start from a keyframe)
|
|
111
|
+
// This limits the maximum latency to 1 keyframe interval
|
|
112
|
+
// (60 frames by default).
|
|
113
|
+
this.#decoder.reset();
|
|
114
|
+
|
|
115
|
+
// `reset` also resets the decoder configuration
|
|
116
|
+
// so we need to re-configure it again.
|
|
117
|
+
this.#decoder.configure(this.#config);
|
|
118
|
+
this.#configured = true;
|
|
119
|
+
} else if (!this.#configured) {
|
|
120
|
+
this.#decoder.configure(this.#config);
|
|
121
|
+
this.#configured = true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
92
125
|
this.#decoder.decode(
|
|
93
126
|
new EncodedVideoChunk({
|
|
94
|
-
//
|
|
95
|
-
type: packet.keyframe
|
|
127
|
+
// AV1 requires Scrcpy 2.0 where `keyframe` flag must be set
|
|
128
|
+
type: packet.keyframe! ? "key" : "delta",
|
|
96
129
|
timestamp: 0,
|
|
97
130
|
data: packet.data,
|
|
98
131
|
}),
|