@yume-chan/scrcpy-decoder-webcodecs 2.5.3 → 3.0.0-beta.0
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/LICENSE +1 -1
- package/README.md +1 -1
- package/esm/video/codec/av1.d.ts +4 -6
- package/esm/video/codec/av1.d.ts.map +1 -1
- package/esm/video/codec/av1.js +29 -95
- package/esm/video/codec/av1.js.map +1 -1
- package/esm/video/codec/h264.d.ts +4 -6
- package/esm/video/codec/h264.d.ts.map +1 -1
- package/esm/video/codec/h264.js +11 -21
- package/esm/video/codec/h264.js.map +1 -1
- package/esm/video/codec/h265.d.ts +4 -6
- package/esm/video/codec/h265.d.ts.map +1 -1
- package/esm/video/codec/h265.js +13 -27
- package/esm/video/codec/h265.js.map +1 -1
- package/esm/video/codec/h26x.d.ts +9 -6
- package/esm/video/codec/h26x.d.ts.map +1 -1
- package/esm/video/codec/h26x.js +25 -69
- package/esm/video/codec/h26x.js.map +1 -1
- package/esm/video/codec/index.d.ts +0 -1
- package/esm/video/codec/index.d.ts.map +1 -1
- package/esm/video/codec/index.js +0 -1
- package/esm/video/codec/index.js.map +1 -1
- package/esm/video/codec/type.d.ts +23 -8
- package/esm/video/codec/type.d.ts.map +1 -1
- package/esm/video/decoder.d.ts +62 -15
- package/esm/video/decoder.d.ts.map +1 -1
- package/esm/video/decoder.js +170 -134
- package/esm/video/decoder.js.map +1 -1
- package/esm/video/index.d.ts +1 -0
- package/esm/video/index.d.ts.map +1 -1
- package/esm/video/index.js +1 -0
- package/esm/video/index.js.map +1 -1
- package/esm/video/render/auto-canvas.d.ts +26 -0
- package/esm/video/render/auto-canvas.d.ts.map +1 -0
- package/esm/video/render/auto-canvas.js +80 -0
- package/esm/video/render/auto-canvas.js.map +1 -0
- package/esm/video/render/bitmap.d.ts +2 -2
- package/esm/video/render/bitmap.d.ts.map +1 -1
- package/esm/video/render/bitmap.js +18 -8
- package/esm/video/render/bitmap.js.map +1 -1
- package/esm/video/render/canvas.d.ts +38 -4
- package/esm/video/render/canvas.d.ts.map +1 -1
- package/esm/video/render/canvas.js +97 -10
- package/esm/video/render/canvas.js.map +1 -1
- package/esm/video/render/flow-control.d.ts +32 -0
- package/esm/video/render/flow-control.d.ts.map +1 -0
- package/esm/video/render/flow-control.js +139 -0
- package/esm/video/render/flow-control.js.map +1 -0
- package/esm/video/render/index.d.ts +2 -0
- package/esm/video/render/index.d.ts.map +1 -1
- package/esm/video/render/index.js +2 -0
- package/esm/video/render/index.js.map +1 -1
- package/esm/video/render/insertable-stream.d.ts +15 -3
- package/esm/video/render/insertable-stream.d.ts.map +1 -1
- package/esm/video/render/insertable-stream.js +29 -11
- package/esm/video/render/insertable-stream.js.map +1 -1
- package/esm/video/render/redraw.d.ts +31 -0
- package/esm/video/render/redraw.d.ts.map +1 -0
- package/esm/video/render/redraw.js +75 -0
- package/esm/video/render/redraw.js.map +1 -0
- package/esm/video/render/type.d.ts +8 -2
- package/esm/video/render/type.d.ts.map +1 -1
- package/esm/video/render/webgl.d.ts +38 -5
- package/esm/video/render/webgl.d.ts.map +1 -1
- package/esm/video/render/webgl.js +228 -59
- package/esm/video/render/webgl.js.map +1 -1
- package/esm/video/utils/index.d.ts +4 -0
- package/esm/video/utils/index.d.ts.map +1 -0
- package/esm/video/utils/index.js +4 -0
- package/esm/video/utils/index.js.map +1 -0
- package/esm/video/utils/snapshot.d.ts +2 -0
- package/esm/video/utils/snapshot.d.ts.map +1 -0
- package/esm/video/utils/snapshot.js +18 -0
- package/esm/video/utils/snapshot.js.map +1 -0
- package/esm/video/utils/timestamp.d.ts +19 -0
- package/esm/video/utils/timestamp.d.ts.map +1 -0
- package/esm/video/utils/timestamp.js +87 -0
- package/esm/video/utils/timestamp.js.map +1 -0
- package/esm/video/utils/video-decoder-stream.d.ts +30 -0
- package/esm/video/utils/video-decoder-stream.d.ts.map +1 -0
- package/esm/video/utils/video-decoder-stream.js +284 -0
- package/esm/video/utils/video-decoder-stream.js.map +1 -0
- package/package.json +12 -11
- package/src/video/codec/av1.ts +41 -131
- package/src/video/codec/h264.ts +15 -37
- package/src/video/codec/h265.ts +16 -45
- package/src/video/codec/h26x.ts +45 -96
- package/src/video/codec/index.ts +0 -1
- package/src/video/codec/type.ts +32 -12
- package/src/video/decoder.ts +203 -165
- package/src/video/index.ts +1 -0
- package/src/video/render/auto-canvas.ts +105 -0
- package/src/video/render/bitmap.ts +23 -9
- package/src/video/render/canvas.ts +157 -12
- package/src/video/render/flow-control.ts +182 -0
- package/src/video/render/index.ts +2 -0
- package/src/video/render/insertable-stream.ts +50 -10
- package/src/video/render/redraw.ts +88 -0
- package/src/video/render/type.ts +10 -2
- package/src/video/render/webgl.ts +316 -80
- package/src/video/utils/index.ts +3 -0
- package/src/video/utils/snapshot.ts +22 -0
- package/src/video/utils/timestamp.ts +108 -0
- package/src/video/utils/video-decoder-stream.ts +406 -0
- package/tsconfig.build.json +0 -14
- package/CHANGELOG.md +0 -140
- package/esm/video/codec/utils.d.ts +0 -4
- package/esm/video/codec/utils.d.ts.map +0 -1
- package/esm/video/codec/utils.js +0 -10
- package/esm/video/codec/utils.js.map +0 -1
- package/esm/video/snapshot.d.ts +0 -6
- package/esm/video/snapshot.d.ts.map +0 -1
- package/esm/video/snapshot.js +0 -41
- package/esm/video/snapshot.js.map +0 -1
- package/src/video/codec/utils.ts +0 -11
- package/src/video/snapshot.ts +0 -41
- package/tsconfig.build.tsbuildinfo +0 -1
package/src/video/codec/h264.ts
CHANGED
|
@@ -1,46 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { H264 } from "@yume-chan/media-codec";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import type { CodecDecoderOptions } from "./type.js";
|
|
5
|
-
import { hexTwoDigits } from "./utils.js";
|
|
3
|
+
import { H26xTransformStream } from "./h26x.js";
|
|
6
4
|
|
|
7
|
-
export class
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
) {
|
|
16
|
-
super(decoder);
|
|
17
|
-
this.#updateSize = updateSize;
|
|
18
|
-
this.#options = options;
|
|
5
|
+
export class H264TransformStream extends H26xTransformStream {
|
|
6
|
+
override convertFrameType(
|
|
7
|
+
keyframe: boolean | undefined,
|
|
8
|
+
data: Uint8Array,
|
|
9
|
+
): EncodedVideoChunkType {
|
|
10
|
+
// Older versions of Scrcpy doesn't have `keyframe` property,
|
|
11
|
+
// so detect it from the frame data.
|
|
12
|
+
return (keyframe ?? H264.containsKeyFrame(data)) ? "key" : "delta";
|
|
19
13
|
}
|
|
20
14
|
|
|
21
|
-
override configure(data: Uint8Array):
|
|
22
|
-
const
|
|
23
|
-
profileIndex,
|
|
24
|
-
constraintSet,
|
|
25
|
-
levelIndex,
|
|
26
|
-
croppedWidth,
|
|
27
|
-
croppedHeight,
|
|
28
|
-
} = h264ParseConfiguration(data);
|
|
29
|
-
|
|
30
|
-
this.#updateSize(croppedWidth, croppedHeight);
|
|
15
|
+
override configure(data: Uint8Array): H26xTransformStream.Config {
|
|
16
|
+
const configuration = H264.parseConfiguration(data);
|
|
31
17
|
|
|
32
|
-
// https://www.rfc-editor.org/rfc/rfc6381#section-3.3
|
|
33
|
-
// ISO Base Media File Format Name Space
|
|
34
|
-
const codec =
|
|
35
|
-
"avc1." +
|
|
36
|
-
hexTwoDigits(profileIndex) +
|
|
37
|
-
hexTwoDigits(constraintSet) +
|
|
38
|
-
hexTwoDigits(levelIndex);
|
|
39
18
|
return {
|
|
40
|
-
codec:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
optimizeForLatency: true,
|
|
19
|
+
codec: H264.toCodecString(configuration),
|
|
20
|
+
codedHeight: configuration.croppedHeight,
|
|
21
|
+
codedWidth: configuration.croppedWidth,
|
|
44
22
|
};
|
|
45
23
|
}
|
|
46
24
|
}
|
package/src/video/codec/h265.ts
CHANGED
|
@@ -1,54 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { h265ParseConfiguration } from "@yume-chan/scrcpy";
|
|
1
|
+
import { H265 } from "@yume-chan/media-codec";
|
|
3
2
|
|
|
4
|
-
import {
|
|
5
|
-
import type { CodecDecoderOptions } from "./type.js";
|
|
6
|
-
import { hexDigits } from "./utils.js";
|
|
3
|
+
import { H26xTransformStream } from "./h26x.js";
|
|
7
4
|
|
|
8
|
-
export class
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
updateSize: (width: number, height: number) => void,
|
|
15
|
-
options?: CodecDecoderOptions,
|
|
16
|
-
) {
|
|
17
|
-
super(decoder);
|
|
18
|
-
this.#updateSize = updateSize;
|
|
19
|
-
this.#options = options;
|
|
5
|
+
export class H265TransformStream extends H26xTransformStream {
|
|
6
|
+
override convertFrameType(
|
|
7
|
+
keyframe: boolean | undefined,
|
|
8
|
+
): EncodedVideoChunkType {
|
|
9
|
+
// H.265 was added in Scrcpy 2.0 which must have `keyframe` property.
|
|
10
|
+
return keyframe ? "key" : "delta";
|
|
20
11
|
}
|
|
21
12
|
|
|
22
|
-
override configure(data: Uint8Array):
|
|
23
|
-
const
|
|
24
|
-
generalProfileSpace,
|
|
25
|
-
generalProfileIndex,
|
|
26
|
-
generalProfileCompatibilitySet,
|
|
27
|
-
generalTierFlag,
|
|
28
|
-
generalLevelIndex,
|
|
29
|
-
generalConstraintSet,
|
|
30
|
-
croppedWidth,
|
|
31
|
-
croppedHeight,
|
|
32
|
-
} = h265ParseConfiguration(data);
|
|
33
|
-
|
|
34
|
-
this.#updateSize(croppedWidth, croppedHeight);
|
|
13
|
+
override configure(data: Uint8Array): H26xTransformStream.Config {
|
|
14
|
+
const configuration = H265.parseConfiguration(data);
|
|
35
15
|
|
|
36
|
-
const codec = [
|
|
37
|
-
"hev1",
|
|
38
|
-
["", "A", "B", "C"][generalProfileSpace]! +
|
|
39
|
-
generalProfileIndex.toString(),
|
|
40
|
-
hexDigits(getUint32LittleEndian(generalProfileCompatibilitySet, 0)),
|
|
41
|
-
(generalTierFlag ? "H" : "L") + generalLevelIndex.toString(),
|
|
42
|
-
...Array.from(generalConstraintSet, hexDigits),
|
|
43
|
-
].join(".");
|
|
44
16
|
return {
|
|
45
|
-
codec,
|
|
46
|
-
// Microsoft Edge requires explicit size
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
optimizeForLatency: true,
|
|
17
|
+
codec: H265.toCodecString(configuration),
|
|
18
|
+
// Microsoft Edge on Windows requires explicit size,
|
|
19
|
+
// otherwise it returns frames in incorrect size.
|
|
20
|
+
// And it needs cropped size, as opposed to the option name.
|
|
21
|
+
codedWidth: configuration.croppedWidth,
|
|
22
|
+
codedHeight: configuration.croppedHeight,
|
|
52
23
|
};
|
|
53
24
|
}
|
|
54
25
|
}
|
package/src/video/codec/h26x.ts
CHANGED
|
@@ -1,101 +1,50 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import { TransformStream } from "@yume-chan/stream-extra";
|
|
2
|
+
|
|
3
|
+
import type { CodecTransformStream } from "./type.js";
|
|
4
|
+
|
|
5
|
+
export abstract class H26xTransformStream
|
|
6
|
+
extends TransformStream<
|
|
7
|
+
CodecTransformStream.Input,
|
|
8
|
+
CodecTransformStream.Output
|
|
9
|
+
>
|
|
10
|
+
implements CodecTransformStream
|
|
11
|
+
{
|
|
12
|
+
constructor() {
|
|
13
|
+
super({
|
|
14
|
+
transform: (packet, controller) => {
|
|
15
|
+
if (packet.type === "configuration") {
|
|
16
|
+
controller.enqueue(this.#configure(packet.data));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
controller.enqueue({
|
|
21
|
+
type: this.convertFrameType(packet.keyframe, packet.data),
|
|
22
|
+
timestamp: packet.timestamp,
|
|
23
|
+
data: packet.data,
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
});
|
|
16
27
|
}
|
|
17
28
|
|
|
18
|
-
abstract
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
data.set(packet.data, raw.length);
|
|
35
|
-
|
|
36
|
-
this.#decoder.decode(
|
|
37
|
-
new EncodedVideoChunk({
|
|
38
|
-
type: "key",
|
|
39
|
-
timestamp: 0,
|
|
40
|
-
data,
|
|
41
|
-
}),
|
|
42
|
-
);
|
|
29
|
+
abstract convertFrameType(
|
|
30
|
+
keyframe: boolean | undefined,
|
|
31
|
+
data: Uint8Array,
|
|
32
|
+
): EncodedVideoChunkType;
|
|
33
|
+
|
|
34
|
+
abstract configure(data: Uint8Array): H26xTransformStream.Config;
|
|
35
|
+
|
|
36
|
+
#configure(data: Uint8Array): CodecTransformStream.Config {
|
|
37
|
+
return {
|
|
38
|
+
...this.configure(data),
|
|
39
|
+
// For H.264 and H.265, when the stream is in Annex B format
|
|
40
|
+
// (which Scrcpy uses, as Android MediaCodec produces),
|
|
41
|
+
// configuration data needs to be combined with the first frame data.
|
|
42
|
+
// https://www.w3.org/TR/webcodecs-avc-codec-registration/#encodedvideochunk-type
|
|
43
|
+
raw: data,
|
|
44
|
+
};
|
|
43
45
|
}
|
|
46
|
+
}
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
this.#config = {
|
|
48
|
-
...this.configure(packet.data),
|
|
49
|
-
raw: packet.data,
|
|
50
|
-
};
|
|
51
|
-
this.#configured = false;
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (!this.#config) {
|
|
56
|
-
throw new Error("Decoder not configured");
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (packet.keyframe) {
|
|
60
|
-
if (this.#decoder.decodeQueueSize) {
|
|
61
|
-
// If the device is too slow to decode all frames,
|
|
62
|
-
// discard queued frames when next keyframe arrives.
|
|
63
|
-
// (can only do this for keyframes because decoding must start from a keyframe)
|
|
64
|
-
// This limits the maximum latency to 1 keyframe interval
|
|
65
|
-
// (60 frames by default).
|
|
66
|
-
this.#decoder.reset();
|
|
67
|
-
|
|
68
|
-
// `reset` also resets the decoder configuration
|
|
69
|
-
// so we need to re-configure it again.
|
|
70
|
-
this.#configureAndDecodeFirstKeyframe(this.#config, packet);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (!this.#configured) {
|
|
75
|
-
this.#configureAndDecodeFirstKeyframe(this.#config, packet);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (!this.#configured) {
|
|
81
|
-
if (packet.keyframe === undefined) {
|
|
82
|
-
// Scrcpy <1.23 doesn't send `keyframe` flag
|
|
83
|
-
// Infer the first frame after configuration as keyframe
|
|
84
|
-
// (`VideoDecoder` will throw error if it's not)
|
|
85
|
-
this.#configureAndDecodeFirstKeyframe(this.#config, packet);
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
throw new Error("Expect a keyframe but got a delta frame");
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
this.#decoder.decode(
|
|
93
|
-
new EncodedVideoChunk({
|
|
94
|
-
// Treat `undefined` as `key`, otherwise won't decode.
|
|
95
|
-
type: packet.keyframe === false ? "delta" : "key",
|
|
96
|
-
timestamp: 0,
|
|
97
|
-
data: packet.data,
|
|
98
|
-
}),
|
|
99
|
-
);
|
|
100
|
-
}
|
|
48
|
+
export namespace H26xTransformStream {
|
|
49
|
+
export type Config = Omit<CodecTransformStream.Config, "raw">;
|
|
101
50
|
}
|
package/src/video/codec/index.ts
CHANGED
package/src/video/codec/type.ts
CHANGED
|
@@ -1,17 +1,37 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ScrcpyMediaStreamConfigurationPacket,
|
|
3
|
+
ScrcpyMediaStreamDataPacket,
|
|
4
|
+
} from "@yume-chan/scrcpy";
|
|
5
|
+
import type { TransformStream } from "@yume-chan/stream-extra";
|
|
2
6
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
export type CodecTransformStream = TransformStream<
|
|
8
|
+
CodecTransformStream.Input,
|
|
9
|
+
CodecTransformStream.Output
|
|
10
|
+
>;
|
|
11
|
+
|
|
12
|
+
export namespace CodecTransformStream {
|
|
13
|
+
export type Input =
|
|
14
|
+
| ScrcpyMediaStreamConfigurationPacket
|
|
15
|
+
| (ScrcpyMediaStreamDataPacket & { timestamp: number });
|
|
16
|
+
|
|
17
|
+
export type Config = VideoDecoderConfig & {
|
|
18
|
+
codedWidth: number;
|
|
19
|
+
codedHeight: number;
|
|
20
|
+
/**
|
|
21
|
+
* Sets an optional raw buffer what will be prepended with the first key frame for decoding.
|
|
22
|
+
*
|
|
23
|
+
* Some codecs (e.g. H.264 and H.265 in Annex B format)
|
|
24
|
+
* send configuration in separate packet,
|
|
25
|
+
* but the configuration also needs to be feed into the decoder.
|
|
26
|
+
*/
|
|
27
|
+
raw?: AllowSharedBufferSource;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type VideoChunk = EncodedVideoChunkInit;
|
|
6
31
|
|
|
7
|
-
export
|
|
8
|
-
hardwareAcceleration?: HardwareAcceleration | undefined;
|
|
32
|
+
export type Output = Config | VideoChunk;
|
|
9
33
|
}
|
|
10
34
|
|
|
11
|
-
export interface
|
|
12
|
-
new (
|
|
13
|
-
decoder: VideoDecoder,
|
|
14
|
-
updateSize: (width: number, height: number) => void,
|
|
15
|
-
options?: CodecDecoderOptions,
|
|
16
|
-
): CodecDecoder;
|
|
35
|
+
export interface CodecTransformStreamConstructor {
|
|
36
|
+
new (): CodecTransformStream;
|
|
17
37
|
}
|