@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.
Files changed (117) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -1
  3. package/esm/video/codec/av1.d.ts +4 -6
  4. package/esm/video/codec/av1.d.ts.map +1 -1
  5. package/esm/video/codec/av1.js +29 -95
  6. package/esm/video/codec/av1.js.map +1 -1
  7. package/esm/video/codec/h264.d.ts +4 -6
  8. package/esm/video/codec/h264.d.ts.map +1 -1
  9. package/esm/video/codec/h264.js +11 -21
  10. package/esm/video/codec/h264.js.map +1 -1
  11. package/esm/video/codec/h265.d.ts +4 -6
  12. package/esm/video/codec/h265.d.ts.map +1 -1
  13. package/esm/video/codec/h265.js +13 -27
  14. package/esm/video/codec/h265.js.map +1 -1
  15. package/esm/video/codec/h26x.d.ts +9 -6
  16. package/esm/video/codec/h26x.d.ts.map +1 -1
  17. package/esm/video/codec/h26x.js +25 -69
  18. package/esm/video/codec/h26x.js.map +1 -1
  19. package/esm/video/codec/index.d.ts +0 -1
  20. package/esm/video/codec/index.d.ts.map +1 -1
  21. package/esm/video/codec/index.js +0 -1
  22. package/esm/video/codec/index.js.map +1 -1
  23. package/esm/video/codec/type.d.ts +23 -8
  24. package/esm/video/codec/type.d.ts.map +1 -1
  25. package/esm/video/decoder.d.ts +62 -15
  26. package/esm/video/decoder.d.ts.map +1 -1
  27. package/esm/video/decoder.js +170 -134
  28. package/esm/video/decoder.js.map +1 -1
  29. package/esm/video/index.d.ts +1 -0
  30. package/esm/video/index.d.ts.map +1 -1
  31. package/esm/video/index.js +1 -0
  32. package/esm/video/index.js.map +1 -1
  33. package/esm/video/render/auto-canvas.d.ts +26 -0
  34. package/esm/video/render/auto-canvas.d.ts.map +1 -0
  35. package/esm/video/render/auto-canvas.js +80 -0
  36. package/esm/video/render/auto-canvas.js.map +1 -0
  37. package/esm/video/render/bitmap.d.ts +2 -2
  38. package/esm/video/render/bitmap.d.ts.map +1 -1
  39. package/esm/video/render/bitmap.js +18 -8
  40. package/esm/video/render/bitmap.js.map +1 -1
  41. package/esm/video/render/canvas.d.ts +38 -4
  42. package/esm/video/render/canvas.d.ts.map +1 -1
  43. package/esm/video/render/canvas.js +97 -10
  44. package/esm/video/render/canvas.js.map +1 -1
  45. package/esm/video/render/flow-control.d.ts +32 -0
  46. package/esm/video/render/flow-control.d.ts.map +1 -0
  47. package/esm/video/render/flow-control.js +139 -0
  48. package/esm/video/render/flow-control.js.map +1 -0
  49. package/esm/video/render/index.d.ts +2 -0
  50. package/esm/video/render/index.d.ts.map +1 -1
  51. package/esm/video/render/index.js +2 -0
  52. package/esm/video/render/index.js.map +1 -1
  53. package/esm/video/render/insertable-stream.d.ts +15 -3
  54. package/esm/video/render/insertable-stream.d.ts.map +1 -1
  55. package/esm/video/render/insertable-stream.js +29 -11
  56. package/esm/video/render/insertable-stream.js.map +1 -1
  57. package/esm/video/render/redraw.d.ts +31 -0
  58. package/esm/video/render/redraw.d.ts.map +1 -0
  59. package/esm/video/render/redraw.js +75 -0
  60. package/esm/video/render/redraw.js.map +1 -0
  61. package/esm/video/render/type.d.ts +8 -2
  62. package/esm/video/render/type.d.ts.map +1 -1
  63. package/esm/video/render/webgl.d.ts +38 -5
  64. package/esm/video/render/webgl.d.ts.map +1 -1
  65. package/esm/video/render/webgl.js +228 -59
  66. package/esm/video/render/webgl.js.map +1 -1
  67. package/esm/video/utils/index.d.ts +4 -0
  68. package/esm/video/utils/index.d.ts.map +1 -0
  69. package/esm/video/utils/index.js +4 -0
  70. package/esm/video/utils/index.js.map +1 -0
  71. package/esm/video/utils/snapshot.d.ts +2 -0
  72. package/esm/video/utils/snapshot.d.ts.map +1 -0
  73. package/esm/video/utils/snapshot.js +18 -0
  74. package/esm/video/utils/snapshot.js.map +1 -0
  75. package/esm/video/utils/timestamp.d.ts +19 -0
  76. package/esm/video/utils/timestamp.d.ts.map +1 -0
  77. package/esm/video/utils/timestamp.js +87 -0
  78. package/esm/video/utils/timestamp.js.map +1 -0
  79. package/esm/video/utils/video-decoder-stream.d.ts +30 -0
  80. package/esm/video/utils/video-decoder-stream.d.ts.map +1 -0
  81. package/esm/video/utils/video-decoder-stream.js +284 -0
  82. package/esm/video/utils/video-decoder-stream.js.map +1 -0
  83. package/package.json +12 -11
  84. package/src/video/codec/av1.ts +41 -131
  85. package/src/video/codec/h264.ts +15 -37
  86. package/src/video/codec/h265.ts +16 -45
  87. package/src/video/codec/h26x.ts +45 -96
  88. package/src/video/codec/index.ts +0 -1
  89. package/src/video/codec/type.ts +32 -12
  90. package/src/video/decoder.ts +203 -165
  91. package/src/video/index.ts +1 -0
  92. package/src/video/render/auto-canvas.ts +105 -0
  93. package/src/video/render/bitmap.ts +23 -9
  94. package/src/video/render/canvas.ts +157 -12
  95. package/src/video/render/flow-control.ts +182 -0
  96. package/src/video/render/index.ts +2 -0
  97. package/src/video/render/insertable-stream.ts +50 -10
  98. package/src/video/render/redraw.ts +88 -0
  99. package/src/video/render/type.ts +10 -2
  100. package/src/video/render/webgl.ts +316 -80
  101. package/src/video/utils/index.ts +3 -0
  102. package/src/video/utils/snapshot.ts +22 -0
  103. package/src/video/utils/timestamp.ts +108 -0
  104. package/src/video/utils/video-decoder-stream.ts +406 -0
  105. package/tsconfig.build.json +0 -14
  106. package/CHANGELOG.md +0 -140
  107. package/esm/video/codec/utils.d.ts +0 -4
  108. package/esm/video/codec/utils.d.ts.map +0 -1
  109. package/esm/video/codec/utils.js +0 -10
  110. package/esm/video/codec/utils.js.map +0 -1
  111. package/esm/video/snapshot.d.ts +0 -6
  112. package/esm/video/snapshot.d.ts.map +0 -1
  113. package/esm/video/snapshot.js +0 -41
  114. package/esm/video/snapshot.js.map +0 -1
  115. package/src/video/codec/utils.ts +0 -11
  116. package/src/video/snapshot.ts +0 -41
  117. package/tsconfig.build.tsbuildinfo +0 -1
@@ -1,8 +1,5 @@
1
- import type { ScrcpyMediaStreamPacket } from "@yume-chan/scrcpy";
2
1
  import { ScrcpyVideoCodecId } from "@yume-chan/scrcpy";
3
- import type { ScrcpyVideoDecoder, ScrcpyVideoDecoderCapability } from "@yume-chan/scrcpy-decoder-tinyh264";
4
- import { WritableStream } from "@yume-chan/stream-extra";
5
- import type { CodecDecoderOptions } from "./codec/type.js";
2
+ import type { ScrcpyVideoDecoder, ScrcpyVideoDecoderCapability } from "@yume-chan/scrcpy-decoder-shared";
6
3
  import type { VideoFrameRenderer } from "./render/index.js";
7
4
  export declare class WebCodecsVideoDecoder implements ScrcpyVideoDecoder {
8
5
  #private;
@@ -10,29 +7,79 @@ export declare class WebCodecsVideoDecoder implements ScrcpyVideoDecoder {
10
7
  static readonly capabilities: Record<string, ScrcpyVideoDecoderCapability>;
11
8
  get codec(): ScrcpyVideoCodecId;
12
9
  get renderer(): VideoFrameRenderer;
13
- get writable(): WritableStream<ScrcpyMediaStreamPacket>;
14
- get framesRendered(): number;
15
- get framesSkipped(): number;
10
+ get rendererType(): ScrcpyVideoDecoder.RendererType;
11
+ get onRendererTypeChange(): import("@yume-chan/event").Event<ScrcpyVideoDecoder.RendererType> | undefined;
12
+ get paused(): boolean;
13
+ get writable(): import("@yume-chan/stream-extra").WritableStream<import("@yume-chan/scrcpy").ScrcpyMediaStreamPacket>;
14
+ get width(): number;
15
+ get height(): number;
16
16
  get sizeChanged(): import("@yume-chan/event").Event<{
17
17
  width: number;
18
18
  height: number;
19
- }, unknown>;
20
- get width(): number;
21
- get height(): number;
19
+ }>;
20
+ get type(): "software" | "hardware";
21
+ get onTypeChange(): import("@yume-chan/event").Event<"software" | "hardware">;
22
+ /**
23
+ * Gets the number of frames waiting to be decoded.
24
+ */
25
+ get decodeQueueSize(): number;
26
+ /**
27
+ * Gets an event when a frame is dequeued (either decoded or discarded).
28
+ */
29
+ get onDequeue(): import("@yume-chan/event").Event<undefined>;
30
+ /**
31
+ * Gets the number of times the decoder has been reset to catch up new keyframes.
32
+ */
33
+ get decoderResetCount(): number;
34
+ /**
35
+ * Gets the number of frames decoded by the decoder.
36
+ */
37
+ get framesDecoded(): number;
38
+ /**
39
+ * Gets the number of frames skipped by the decoder.
40
+ */
41
+ get framesSkippedDecoding(): number;
42
+ /**
43
+ * Gets the total time spent processing and decoding frames in milliseconds.
44
+ */
45
+ get totalDecodeTime(): number;
46
+ /**
47
+ * Gets the number of frames that have been drawn on the renderer.
48
+ */
49
+ get framesRendered(): number;
50
+ /**
51
+ * Gets the number of frames that's visible to the user.
52
+ *
53
+ * Multiple frames might be rendered during one vertical sync interval,
54
+ * but only the last of them is represented to the user.
55
+ * This costs some performance but reduces latency by 1 frame.
56
+ *
57
+ * Might be `0` if the renderer is in a nested Web Worker on Chrome due to a Chrome bug.
58
+ * https://issues.chromium.org/issues/41483010
59
+ */
60
+ get framesDisplayed(): number;
61
+ /**
62
+ * Gets the number of frames that wasn't drawn on the renderer
63
+ * because the renderer can't keep up
64
+ */
65
+ get framesSkippedRendering(): number;
22
66
  /**
23
67
  * Create a new WebCodecs video decoder.
24
68
  */
25
- constructor({ codec, renderer, ...options }: WebCodecsVideoDecoder.Options);
26
- snapshot(): Promise<Blob | undefined>;
27
- dispose(): void;
69
+ constructor({ codec, renderer, hardwareAcceleration, optimizeForLatency, }: WebCodecsVideoDecoder.Options);
70
+ pause(): void;
71
+ resume(): undefined;
72
+ trackDocumentVisibility(document: Document): () => undefined;
73
+ snapshot(options?: ImageEncodeOptions): Promise<Blob | undefined>;
74
+ dispose(): undefined;
28
75
  }
29
76
  export declare namespace WebCodecsVideoDecoder {
30
- interface Options extends CodecDecoderOptions {
77
+ interface Options extends Pick<VideoDecoderConfig, "hardwareAcceleration" | "optimizeForLatency"> {
31
78
  /**
32
79
  * The video codec to decode
33
80
  */
34
81
  codec: ScrcpyVideoCodecId;
35
- renderer: VideoFrameRenderer;
82
+ renderer?: VideoFrameRenderer | undefined;
36
83
  }
37
84
  }
38
85
  //# sourceMappingURL=decoder.d.ts.map
@@ -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;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"}
1
+ {"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../src/video/decoder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAuB,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EACR,kBAAkB,EAClB,4BAA4B,EAC/B,MAAM,kCAAkC,CAAC;AAU1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQ5D,qBAAa,qBAAsB,YAAW,kBAAkB;;IAC5D,MAAM,KAAK,WAAW,YAErB;IAED,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAKpE;IAKN,IAAI,KAAK,uBAER;IAGD,IAAI,QAAQ,uBAEX;IACD,IAAI,YAAY,oCAEf;IACD,IAAI,oBAAoB,kFAEvB;IAOD,IAAI,MAAM,YAET;IACD,IAAI,QAAQ,0GAEX;IAOD,IAAI,KAAK,WAER;IACD,IAAI,MAAM,WAET;IACD,IAAI,WAAW;;;OAEd;IAOD,IAAI,IAAI,4BAIP;IAKD,IAAI,YAAY,8DAEf;IACD;;OAEG;IACH,IAAI,eAAe,WAElB;IACD;;OAEG;IACH,IAAI,SAAS,gDAEZ;IACD;;OAEG;IACH,IAAI,iBAAiB,WAEpB;IACD;;OAEG;IACH,IAAI,aAAa,WAEhB;IACD;;OAEG;IACH,IAAI,qBAAqB,WAExB;IAKD;;OAEG;IACH,IAAI,eAAe,WAElB;IAKD;;OAEG;IACH,IAAI,cAAc,WAEjB;IACD;;;;;;;;;OASG;IACH,IAAI,eAAe,WAElB;IACD;;;OAGG;IACH,IAAI,sBAAsB,WAEzB;IAID;;OAEG;gBACS,EACR,KAAK,EACL,QAAmC,EACnC,oBAAsC,EACtC,kBAAyB,GAC5B,EAAE,qBAAqB,CAAC,OAAO;IAgDhC,KAAK,IAAI,IAAI;IAIb,MAAM,IAAI,SAAS;IAInB,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,SAAS;IAItD,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB;IA2B3C,OAAO,IAAI,SAAS;CAUvB;AAED,yBAAiB,qBAAqB,CAAC;IACnC,UAAiB,OAAQ,SAAQ,IAAI,CACjC,kBAAkB,EAClB,sBAAsB,GAAG,oBAAoB,CAChD;QACG;;WAEG;QACH,KAAK,EAAE,kBAAkB,CAAC;QAE1B,QAAQ,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;KAC7C;CACJ"}
@@ -1,12 +1,10 @@
1
- import { StickyEventEmitter } from "@yume-chan/event";
2
- import { ScrcpyVideoCodecId } from "@yume-chan/scrcpy";
3
- import { WritableStream } from "@yume-chan/stream-extra";
4
- import { Av1Codec, H264Decoder, H265Decoder } from "./codec/index.js";
5
- import { Pool } from "./pool.js";
6
- import { VideoFrameCapturer } from "./snapshot.js";
7
- const VideoFrameCapturerPool =
8
- /* #__PURE__ */
9
- new Pool(() => new VideoFrameCapturer(), 4);
1
+ import { pipe } from "@yume-chan/event";
2
+ import { ScrcpyVideoCodecId, ScrcpyVideoSizeImpl } from "@yume-chan/scrcpy";
3
+ import { ScrcpyVideoDecoderPauseController } from "@yume-chan/scrcpy-decoder-shared";
4
+ import { InspectStream } from "@yume-chan/stream-extra";
5
+ import { Av1TransformStream, H264TransformStream, H265TransformStream, } from "./codec/index.js";
6
+ import { AutoCanvasRenderer, BitmapVideoFrameRenderer, RendererController, } from "./render/index.js";
7
+ import { TimestampTransforms, VideoDecoderStream } from "./utils/index.js";
10
8
  export class WebCodecsVideoDecoder {
11
9
  static get isSupported() {
12
10
  return typeof globalThis.VideoDecoder !== "undefined";
@@ -16,6 +14,7 @@ export class WebCodecsVideoDecoder {
16
14
  h265: {},
17
15
  av1: {},
18
16
  };
17
+ // #region parameters
19
18
  #codec;
20
19
  get codec() {
21
20
  return this.#codec;
@@ -24,162 +23,199 @@ export class WebCodecsVideoDecoder {
24
23
  get renderer() {
25
24
  return this.#renderer;
26
25
  }
27
- #options;
28
- #codecDecoder;
29
- #writable;
30
- get writable() {
31
- return this.#writable;
26
+ get rendererType() {
27
+ return this.#renderer.type;
32
28
  }
33
- #error;
34
- #controller;
35
- #framesDraw = 0;
36
- #framesPresented = 0;
37
- get framesRendered() {
38
- return this.#framesPresented;
29
+ get onRendererTypeChange() {
30
+ return this.#renderer.onTypeChanged;
39
31
  }
40
- #framesSkipped = 0;
41
- get framesSkipped() {
42
- return this.#framesSkipped;
32
+ // #endregion parameters
33
+ // #region pause controller
34
+ #pause = new ScrcpyVideoDecoderPauseController();
35
+ get paused() {
36
+ return this.#pause.paused;
43
37
  }
44
- #sizeChanged = new StickyEventEmitter();
45
- get sizeChanged() {
46
- return this.#sizeChanged.event;
38
+ get writable() {
39
+ return this.#pause.writable;
47
40
  }
48
- #width = 0;
41
+ // #endregion pause controller
42
+ // #region size
43
+ #size = new ScrcpyVideoSizeImpl();
49
44
  get width() {
50
- return this.#width;
45
+ return this.#size.width;
51
46
  }
52
- #height = 0;
53
47
  get height() {
54
- return this.#height;
48
+ return this.#size.height;
49
+ }
50
+ get sizeChanged() {
51
+ return this.#size.sizeChanged;
52
+ }
53
+ // #endregion size
54
+ // #region raw decoder
55
+ #rawDecoder = new VideoDecoderStream();
56
+ get type() {
57
+ return this.#rawDecoder.hardwareAcceleration !== "prefer-software"
58
+ ? "hardware"
59
+ : "software";
60
+ }
61
+ #onTypeChange = pipe(this.#rawDecoder.onHardwareAccelerationChange, (value) => (value !== "prefer-software" ? "hardware" : "software"));
62
+ get onTypeChange() {
63
+ return this.#onTypeChange;
64
+ }
65
+ /**
66
+ * Gets the number of frames waiting to be decoded.
67
+ */
68
+ get decodeQueueSize() {
69
+ return this.#rawDecoder.decodeQueueSize;
70
+ }
71
+ /**
72
+ * Gets an event when a frame is dequeued (either decoded or discarded).
73
+ */
74
+ get onDequeue() {
75
+ return this.#rawDecoder.onDequeue;
55
76
  }
56
- #decoder;
57
- #drawing = false;
58
- #nextFrame;
59
- #captureFrame;
60
- #animationFrameId = 0;
77
+ /**
78
+ * Gets the number of times the decoder has been reset to catch up new keyframes.
79
+ */
80
+ get decoderResetCount() {
81
+ return this.#rawDecoder.decoderResetCount;
82
+ }
83
+ /**
84
+ * Gets the number of frames decoded by the decoder.
85
+ */
86
+ get framesDecoded() {
87
+ return this.#rawDecoder.framesDecoded;
88
+ }
89
+ /**
90
+ * Gets the number of frames skipped by the decoder.
91
+ */
92
+ get framesSkippedDecoding() {
93
+ return this.#rawDecoder.framesSkippedDecoding;
94
+ }
95
+ // #endregion raw decoder
96
+ #timestampTransforms = new TimestampTransforms();
97
+ /**
98
+ * Gets the total time spent processing and decoding frames in milliseconds.
99
+ */
100
+ get totalDecodeTime() {
101
+ return this.#timestampTransforms.totalDecodeTime;
102
+ }
103
+ // #region renderer
104
+ #renderController = new RendererController();
105
+ /**
106
+ * Gets the number of frames that have been drawn on the renderer.
107
+ */
108
+ get framesRendered() {
109
+ return this.#renderController.framesRendered;
110
+ }
111
+ /**
112
+ * Gets the number of frames that's visible to the user.
113
+ *
114
+ * Multiple frames might be rendered during one vertical sync interval,
115
+ * but only the last of them is represented to the user.
116
+ * This costs some performance but reduces latency by 1 frame.
117
+ *
118
+ * Might be `0` if the renderer is in a nested Web Worker on Chrome due to a Chrome bug.
119
+ * https://issues.chromium.org/issues/41483010
120
+ */
121
+ get framesDisplayed() {
122
+ return this.#renderController.framesDisplayed;
123
+ }
124
+ /**
125
+ * Gets the number of frames that wasn't drawn on the renderer
126
+ * because the renderer can't keep up
127
+ */
128
+ get framesSkippedRendering() {
129
+ return this.#renderController.framesSkippedRendering;
130
+ }
131
+ // #endregion renderer
61
132
  /**
62
133
  * Create a new WebCodecs video decoder.
63
134
  */
64
- constructor({ codec, renderer, ...options }) {
135
+ constructor({ codec, renderer = new AutoCanvasRenderer(), hardwareAcceleration = "no-preference", optimizeForLatency = true, }) {
65
136
  this.#codec = codec;
66
137
  this.#renderer = renderer;
67
- this.#options = options;
68
- this.#decoder = new VideoDecoder({
69
- output: (frame) => {
70
- this.#captureFrame?.close();
71
- // PERF: `VideoFrame#clone` is cheap
72
- this.#captureFrame = frame.clone();
73
- if (this.#drawing) {
74
- if (this.#nextFrame) {
75
- this.#nextFrame.close();
76
- this.#framesSkipped += 1;
77
- }
78
- this.#nextFrame = frame;
79
- return;
80
- }
81
- void this.#draw(frame);
82
- },
83
- error: (error) => {
84
- this.#setError(error);
85
- },
86
- });
138
+ let codecTransform;
87
139
  switch (this.#codec) {
88
140
  case ScrcpyVideoCodecId.H264:
89
- this.#codecDecoder = new H264Decoder(this.#decoder, this.#updateSize, this.#options);
141
+ codecTransform = new H264TransformStream();
90
142
  break;
91
143
  case ScrcpyVideoCodecId.H265:
92
- this.#codecDecoder = new H265Decoder(this.#decoder, this.#updateSize, this.#options);
144
+ codecTransform = new H265TransformStream();
93
145
  break;
94
146
  case ScrcpyVideoCodecId.AV1:
95
- this.#codecDecoder = new Av1Codec(this.#decoder, this.#updateSize, this.#options);
147
+ codecTransform = new Av1TransformStream();
96
148
  break;
97
149
  default:
150
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
98
151
  throw new Error(`Unsupported codec: ${this.#codec}`);
99
152
  }
100
- this.#writable = new WritableStream({
101
- start: (controller) => {
102
- if (this.#error) {
103
- controller.error(this.#error);
104
- }
105
- else {
106
- this.#controller = controller;
107
- }
108
- },
109
- write: (packet) => {
110
- this.#codecDecoder.decode(packet);
111
- },
112
- });
113
- this.#handleAnimationFrame();
114
- }
115
- #setError(error) {
116
- if (this.#controller) {
117
- try {
118
- this.#controller.error(error);
119
- }
120
- catch {
121
- // ignore
153
+ void this.#pause.readable
154
+ // Add timestamp
155
+ .pipeThrough(this.#timestampTransforms.addTimestamp)
156
+ // Convert Scrcpy packets to `VideoDecoder` config/chunk
157
+ .pipeThrough(codecTransform)
158
+ // Insert extra `VideoDecoder` config and intercept size changes
159
+ .pipeThrough(new InspectStream((chunk) => {
160
+ if ("codec" in chunk) {
161
+ chunk.hardwareAcceleration = hardwareAcceleration;
162
+ chunk.optimizeForLatency = optimizeForLatency;
163
+ this.#size.setSize(chunk.codedWidth, chunk.codedHeight);
122
164
  }
123
- }
124
- else {
125
- this.#error = error;
126
- }
165
+ }))
166
+ // Decode `VideoDecoder` config/chunk to `VideoFrame`s
167
+ .pipeThrough(this.#rawDecoder)
168
+ // Track decoding time and filter skipped frames
169
+ .pipeThrough(this.#timestampTransforms.consumeTimestamp)
170
+ // Skip frames if renderer can't keep up
171
+ .pipeThrough(this.#renderController)
172
+ // Render
173
+ .pipeTo(renderer.writable)
174
+ // Errors will be handled by source stream
175
+ .catch(() => { });
127
176
  }
128
- async #draw(frame) {
129
- try {
130
- this.#drawing = true;
131
- // PERF: Draw every frame to minimize latency at cost of performance.
132
- // When multiple frames are drawn in one vertical sync interval,
133
- // only the last one is visible to users.
134
- // But this ensures users can always see the most up-to-date screen.
135
- // This is also the behavior of official Scrcpy client.
136
- // https://github.com/Genymobile/scrcpy/issues/3679
137
- this.#updateSize(frame.displayWidth, frame.displayHeight);
138
- await this.#renderer.draw(frame);
139
- this.#framesDraw += 1;
140
- frame.close();
141
- if (this.#nextFrame) {
142
- const frame = this.#nextFrame;
143
- this.#nextFrame = undefined;
144
- await this.#draw(frame);
145
- }
146
- this.#drawing = false;
147
- }
148
- catch (error) {
149
- this.#setError(error);
150
- }
177
+ pause() {
178
+ this.#pause.pause();
151
179
  }
152
- #updateSize = (width, height) => {
153
- this.#renderer.setSize(width, height);
154
- this.#width = width;
155
- this.#height = height;
156
- this.#sizeChanged.fire({ width, height });
157
- };
158
- #handleAnimationFrame = () => {
159
- if (this.#framesDraw > 0) {
160
- this.#framesPresented += 1;
161
- this.#framesSkipped += this.#framesDraw - 1;
162
- this.#framesDraw = 0;
163
- }
164
- this.#animationFrameId = requestAnimationFrame(this.#handleAnimationFrame);
165
- };
166
- async snapshot() {
167
- const frame = this.#captureFrame;
180
+ resume() {
181
+ this.#pause.resume();
182
+ }
183
+ trackDocumentVisibility(document) {
184
+ return this.#pause.trackDocumentVisibility(document);
185
+ }
186
+ async snapshot(options) {
187
+ const frame = this.#renderController.captureFrame;
168
188
  if (!frame) {
169
189
  return undefined;
170
190
  }
171
- const capturer = await VideoFrameCapturerPool.borrow();
172
- const result = await capturer.capture(frame);
173
- VideoFrameCapturerPool.return(capturer);
174
- return result;
191
+ // First check if the renderer can provide a snapshot natively
192
+ const blob = await this.#renderer.snapshot?.(options);
193
+ if (blob) {
194
+ return blob;
195
+ }
196
+ // Create a BitmapVideoFrameRenderer to draw the frame
197
+ const renderer = new BitmapVideoFrameRenderer();
198
+ try {
199
+ const writer = renderer.writable.getWriter();
200
+ // Draw the frame
201
+ // `renderer` will close the passed in `frame`, so make a clone
202
+ await writer.write(frame.clone());
203
+ await writer.close();
204
+ // BitmapVideoFrameRenderer.snapshot will definitely return a value
205
+ return await renderer.snapshot(options);
206
+ }
207
+ finally {
208
+ renderer.dispose();
209
+ }
175
210
  }
176
211
  dispose() {
177
- cancelAnimationFrame(this.#animationFrameId);
178
- if (this.#decoder.state !== "closed") {
179
- this.#decoder.close();
180
- }
181
- this.#nextFrame?.close();
182
- this.#captureFrame?.close();
212
+ // Most cleanup happens automatically when `writable` ends
213
+ // (in each stream's `close` callback).
214
+ // This method cleanup things that still available after `writable` ends
215
+ this.#pause.dispose();
216
+ this.#size.dispose();
217
+ this.#renderController.dispose();
218
+ this.#renderer.dispose?.();
183
219
  }
184
220
  }
185
221
  //# sourceMappingURL=decoder.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"decoder.js","sourceRoot":"","sources":["../../src/video/decoder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decoder.js","sourceRoot":"","sources":["../../src/video/decoder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAK5E,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EACH,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACH,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3E,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,qBAAqB;IAErB,MAAM,CAAqB;IAC3B,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,SAAS,CAAqB;IAC9B,IAAI,QAAQ;QACR,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IACD,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC/B,CAAC;IACD,IAAI,oBAAoB;QACpB,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;IACxC,CAAC;IAED,wBAAwB;IAExB,2BAA2B;IAE3B,MAAM,GAAG,IAAI,iCAAiC,EAAE,CAAC;IACjD,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;IACD,IAAI,QAAQ;QACR,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAChC,CAAC;IAED,8BAA8B;IAE9B,eAAe;IAEf,KAAK,GAAG,IAAI,mBAAmB,EAAE,CAAC;IAClC,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;IAC5B,CAAC;IACD,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC7B,CAAC;IACD,IAAI,WAAW;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;IAClC,CAAC;IAED,kBAAkB;IAElB,sBAAsB;IAEtB,WAAW,GAAG,IAAI,kBAAkB,EAAE,CAAC;IACvC,IAAI,IAAI;QACJ,OAAO,IAAI,CAAC,WAAW,CAAC,oBAAoB,KAAK,iBAAiB;YAC9D,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,UAAU,CAAC;IACrB,CAAC;IACD,aAAa,GAAG,IAAI,CAChB,IAAI,CAAC,WAAW,CAAC,4BAA4B,EAC7C,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CACrE,CAAC;IACF,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IACD;;OAEG;IACH,IAAI,eAAe;QACf,OAAO,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC;IAC5C,CAAC;IACD;;OAEG;IACH,IAAI,SAAS;QACT,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC;IACtC,CAAC;IACD;;OAEG;IACH,IAAI,iBAAiB;QACjB,OAAO,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC;IAC9C,CAAC;IACD;;OAEG;IACH,IAAI,aAAa;QACb,OAAO,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC;IAC1C,CAAC;IACD;;OAEG;IACH,IAAI,qBAAqB;QACrB,OAAO,IAAI,CAAC,WAAW,CAAC,qBAAqB,CAAC;IAClD,CAAC;IAED,yBAAyB;IAEzB,oBAAoB,GAAG,IAAI,mBAAmB,EAAE,CAAC;IACjD;;OAEG;IACH,IAAI,eAAe;QACf,OAAO,IAAI,CAAC,oBAAoB,CAAC,eAAe,CAAC;IACrD,CAAC;IAED,mBAAmB;IAEnB,iBAAiB,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAC7C;;OAEG;IACH,IAAI,cAAc;QACd,OAAO,IAAI,CAAC,iBAAiB,CAAC,cAAc,CAAC;IACjD,CAAC;IACD;;;;;;;;;OASG;IACH,IAAI,eAAe;QACf,OAAO,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC;IAClD,CAAC;IACD;;;OAGG;IACH,IAAI,sBAAsB;QACtB,OAAO,IAAI,CAAC,iBAAiB,CAAC,sBAAsB,CAAC;IACzD,CAAC;IAED,sBAAsB;IAEtB;;OAEG;IACH,YAAY,EACR,KAAK,EACL,QAAQ,GAAG,IAAI,kBAAkB,EAAE,EACnC,oBAAoB,GAAG,eAAe,EACtC,kBAAkB,GAAG,IAAI,GACG;QAC5B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAE1B,IAAI,cAAoC,CAAC;QACzC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;YAClB,KAAK,kBAAkB,CAAC,IAAI;gBACxB,cAAc,GAAG,IAAI,mBAAmB,EAAE,CAAC;gBAC3C,MAAM;YACV,KAAK,kBAAkB,CAAC,IAAI;gBACxB,cAAc,GAAG,IAAI,mBAAmB,EAAE,CAAC;gBAC3C,MAAM;YACV,KAAK,kBAAkB,CAAC,GAAG;gBACvB,cAAc,GAAG,IAAI,kBAAkB,EAAE,CAAC;gBAC1C,MAAM;YACV;gBACI,4EAA4E;gBAC5E,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,KAAK,IAAI,CAAC,MAAM,CAAC,QAAQ;YACrB,gBAAgB;aACf,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,YAAY,CAAC;YACpD,wDAAwD;aACvD,WAAW,CAAC,cAAc,CAAC;YAC5B,gEAAgE;aAC/D,WAAW,CACR,IAAI,aAAa,CAAC,CAAC,KAAK,EAAa,EAAE;YACnC,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;gBACnB,KAAK,CAAC,oBAAoB,GAAG,oBAAoB,CAAC;gBAClD,KAAK,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;gBAE9C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;YAC5D,CAAC;QACL,CAAC,CAAC,CACL;YACD,sDAAsD;aACrD,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC;YAC9B,gDAAgD;aAC/C,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,gBAAgB,CAAC;YACxD,wCAAwC;aACvC,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC;YACpC,SAAS;aACR,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC1B,0CAA0C;aACzC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACzB,CAAC;IAED,KAAK;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,MAAM;QACF,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IACzB,CAAC;IAED,uBAAuB,CAAC,QAAkB;QACtC,OAAO,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAA4B;QACvC,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,OAAO,SAAS,CAAC;QACrB,CAAC;QAED,8DAA8D;QAC9D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,IAAI,EAAE,CAAC;YACP,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,sDAAsD;QACtD,MAAM,QAAQ,GAAG,IAAI,wBAAwB,EAAE,CAAC;QAChD,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YAC7C,iBAAiB;YACjB,+DAA+D;YAC/D,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;YAClC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,mEAAmE;YACnE,OAAO,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC5C,CAAC;gBAAS,CAAC;YACP,QAAQ,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC;IACL,CAAC;IAED,OAAO;QACH,0DAA0D;QAC1D,uCAAuC;QACvC,wEAAwE;QAExE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACrB,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;IAC/B,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export * from "./codec/index.js";
2
2
  export * from "./decoder.js";
3
3
  export * from "./render/index.js";
4
+ export * from "./utils/index.js";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/video/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/video/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export * from "./codec/index.js";
2
2
  export * from "./decoder.js";
3
3
  export * from "./render/index.js";
4
+ export * from "./utils/index.js";
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/video/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/video/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ScrcpyVideoDecoder } from "@yume-chan/scrcpy-decoder-shared";
2
+ import { WritableStream } from "@yume-chan/stream-extra";
3
+ import type { VideoFrameRenderer } from "./type.js";
4
+ import { WebGLVideoFrameRenderer } from "./webgl.js";
5
+ export declare class AutoCanvasRenderer implements VideoFrameRenderer {
6
+ #private;
7
+ get type(): ScrcpyVideoDecoder.RendererType;
8
+ get onTypeChanged(): import("@yume-chan/event").Event<ScrcpyVideoDecoder.RendererType>;
9
+ /**
10
+ * Gets the canvas used by the renderer.
11
+ *
12
+ * The `canvas` property might change when the renderer switches between WebGL and 2D rendering.
13
+ * Specify a `createCanvas` option, or listen to the `onTypeChanged` event to handle the canvas change.
14
+ */
15
+ get canvas(): HTMLCanvasElement | OffscreenCanvas;
16
+ get writable(): WritableStream<VideoFrame>;
17
+ constructor(options?: AutoCanvasRenderer.Options);
18
+ snapshot(options?: ImageEncodeOptions): Promise<Blob | undefined>;
19
+ dispose(): undefined;
20
+ }
21
+ export declare namespace AutoCanvasRenderer {
22
+ interface Options extends Omit<WebGLVideoFrameRenderer.Options, "canvas"> {
23
+ createCanvas?: () => HTMLCanvasElement | OffscreenCanvas;
24
+ }
25
+ }
26
+ //# sourceMappingURL=auto-canvas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-canvas.d.ts","sourceRoot":"","sources":["../../../src/video/render/auto-canvas.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAIzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAErD,qBAAa,kBAAmB,YAAW,kBAAkB;;IAIzD,IAAI,IAAI,oCAEP;IAED,IAAI,aAAa,sEAEhB;IAGD;;;;;OAKG;IACH,IAAI,MAAM,wCAET;IAeD,IAAI,QAAQ,+BAEX;gBAEW,OAAO,CAAC,EAAE,kBAAkB,CAAC,OAAO;IAiChD,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAIjE,OAAO;CAQV;AAED,yBAAiB,kBAAkB,CAAC;IAChC,UAAiB,OAAQ,SAAQ,IAAI,CACjC,uBAAuB,CAAC,OAAO,EAC/B,QAAQ,CACX;QACG,YAAY,CAAC,EAAE,MAAM,iBAAiB,GAAG,eAAe,CAAC;KAC5D;CACJ"}
@@ -0,0 +1,80 @@
1
+ import { StickyEventEmitter } from "@yume-chan/event";
2
+ import { createCanvas } from "@yume-chan/scrcpy-decoder-shared";
3
+ import { WritableStream } from "@yume-chan/stream-extra";
4
+ import { BitmapVideoFrameRenderer } from "./bitmap.js";
5
+ import { WebGLVideoFrameRenderer } from "./webgl.js";
6
+ export class AutoCanvasRenderer {
7
+ #inner;
8
+ #innerWriter;
9
+ get type() {
10
+ return this.#inner.type;
11
+ }
12
+ #onTypeChanged = new StickyEventEmitter();
13
+ get onTypeChanged() {
14
+ return this.#onTypeChanged.event;
15
+ }
16
+ #canvas;
17
+ /**
18
+ * Gets the canvas used by the renderer.
19
+ *
20
+ * The `canvas` property might change when the renderer switches between WebGL and 2D rendering.
21
+ * Specify a `createCanvas` option, or listen to the `onTypeChanged` event to handle the canvas change.
22
+ */
23
+ get canvas() {
24
+ return this.#canvas;
25
+ }
26
+ #lastFrame;
27
+ #writableController;
28
+ #writable = new WritableStream({
29
+ start: (controller) => {
30
+ this.#writableController = controller;
31
+ },
32
+ write: async (frame) => {
33
+ this.#lastFrame?.close();
34
+ this.#lastFrame = frame.clone();
35
+ await this.#innerWriter.write(frame);
36
+ },
37
+ });
38
+ get writable() {
39
+ return this.#writable;
40
+ }
41
+ constructor(options) {
42
+ this.#createInner(options, WebGLVideoFrameRenderer.isSupported);
43
+ }
44
+ #createInner(options, webgl) {
45
+ this.#canvas = options?.createCanvas?.() ?? createCanvas();
46
+ if (webgl) {
47
+ const webgl = new WebGLVideoFrameRenderer({
48
+ ...options,
49
+ canvas: this.#canvas,
50
+ });
51
+ webgl.onContextLost(() => {
52
+ this.#createInner(options, false);
53
+ if (this.#lastFrame) {
54
+ this.#innerWriter
55
+ .write(this.#lastFrame.clone())
56
+ .catch((e) => this.#writableController.error(e));
57
+ }
58
+ });
59
+ this.#inner = webgl;
60
+ }
61
+ else {
62
+ this.#inner = new BitmapVideoFrameRenderer({
63
+ ...options,
64
+ canvas: this.#canvas,
65
+ });
66
+ }
67
+ this.#innerWriter = this.#inner.writable.getWriter();
68
+ this.#onTypeChanged.fire(this.#inner.type);
69
+ }
70
+ snapshot(options) {
71
+ return this.#inner.snapshot(options);
72
+ }
73
+ dispose() {
74
+ this.#onTypeChanged.dispose();
75
+ this.#lastFrame?.close();
76
+ this.#lastFrame = undefined;
77
+ return this.#inner.dispose();
78
+ }
79
+ }
80
+ //# sourceMappingURL=auto-canvas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-canvas.js","sourceRoot":"","sources":["../../../src/video/render/auto-canvas.ts"],"names":[],"mappings":"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"}