@pexip/media-processor 20.3.5 → 22.0.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 (201) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/README.md +17 -10
  3. package/api-docs/README.mdx +69 -23
  4. package/api-docs/functions/assertMediaStreamVideoTrack.mdx +13 -0
  5. package/api-docs/functions/createBenchmark.mdx +17 -5
  6. package/api-docs/functions/createFrameCallbackRequest.mdx +8 -2
  7. package/api-docs/functions/createMediaStreamTrackInputProcessAdaptor.mdx +10 -0
  8. package/api-docs/functions/createReadWritableStreamFallbackInputProcessAdaptor.mdx +17 -0
  9. package/api-docs/functions/createReadWritableStreamInputProcessAdaptor.mdx +10 -0
  10. package/api-docs/functions/createVideoProcessor.mdx +3 -3
  11. package/api-docs/functions/createWindowedStats.mdx +23 -0
  12. package/api-docs/functions/getDefaultInputProcessAdaptor.mdx +17 -0
  13. package/api-docs/functions/iou.mdx +19 -0
  14. package/api-docs/functions/isMediaStreamVideoTrack.mdx +13 -0
  15. package/api-docs/functions/labelComponents.mdx +20 -0
  16. package/api-docs/functions/nearestPowerOfTwo.mdx +21 -0
  17. package/api-docs/functions/playVideo.mdx +16 -0
  18. package/api-docs/functions/scoreComponent.mdx +22 -0
  19. package/api-docs/functions/setVideoElementSrc.mdx +14 -0
  20. package/api-docs/interfaces/Analyzer.mdx +4 -0
  21. package/api-docs/interfaces/Benchmark.mdx +26 -2
  22. package/api-docs/interfaces/FrameTransformStats.mdx +9 -0
  23. package/api-docs/interfaces/Gain.mdx +4 -0
  24. package/api-docs/interfaces/ImageSegmenterOptions.mdx +0 -2
  25. package/api-docs/interfaces/InputProcessAdaptor.mdx +28 -0
  26. package/api-docs/interfaces/Process.mdx +8 -3
  27. package/api-docs/interfaces/ProcessEventMute.mdx +6 -0
  28. package/api-docs/interfaces/ProcessWorkerEventOpened.mdx +7 -0
  29. package/api-docs/interfaces/ProcessWorkerEventStats.mdx +6 -0
  30. package/api-docs/interfaces/ProcessWorkerEventUpdated.mdx +7 -0
  31. package/api-docs/interfaces/ProcessorEvent.mdx +1 -1
  32. package/api-docs/interfaces/ProcessorOptions.mdx +0 -1
  33. package/api-docs/interfaces/ProcessorProcessOptions.mdx +3 -1
  34. package/api-docs/interfaces/ProcessorUpdateOptions.mdx +15 -0
  35. package/api-docs/interfaces/ReadWritableStream.mdx +12 -0
  36. package/api-docs/interfaces/Renderer.mdx +2 -2
  37. package/api-docs/interfaces/RendererOptions.mdx +25 -12
  38. package/api-docs/interfaces/Segmenter.mdx +89 -10
  39. package/api-docs/interfaces/SegmenterOptions.mdx +0 -1
  40. package/api-docs/interfaces/SelectionOptions.mdx +15 -0
  41. package/api-docs/interfaces/Stats.mdx +11 -0
  42. package/api-docs/interfaces/VideoProcessor.mdx +49 -5
  43. package/api-docs/interfaces/Weights.mdx +12 -0
  44. package/api-docs/type-aliases/OptionalKeys.mdx +10 -0
  45. package/api-docs/type-aliases/ProcessEvents.mdx +1 -0
  46. package/api-docs/type-aliases/ProcessInputType.mdx +3 -1
  47. package/api-docs/type-aliases/ProcessWorkerEvents.mdx +6 -4
  48. package/api-docs/type-aliases/ProcessorWorkerEvents.mdx +1 -1
  49. package/api-docs/type-aliases/Struct.mdx +9 -0
  50. package/api-docs/variables/BACKGROUND_THRESHOLD.mdx +3 -0
  51. package/api-docs/variables/DOWN_SAMPLE_FACTOR.mdx +3 -0
  52. package/api-docs/variables/EDGE_BLUR_AMOUNT.mdx +1 -1
  53. package/api-docs/variables/EXCLUDE_BYSTANDERS.mdx +3 -0
  54. package/api-docs/variables/FOREGROUND_THRESHOLD.mdx +1 -1
  55. package/api-docs/variables/FRAME_RATE.mdx +1 -1
  56. package/api-docs/variables/ImageFetchError.mdx +3 -0
  57. package/api-docs/variables/LIGHT_WRAP_BLUR_AMOUNT.mdx +3 -0
  58. package/api-docs/variables/LIGHT_WRAP_EDGE_BAND.mdx +3 -0
  59. package/api-docs/variables/LIGHT_WRAP_INTENSITY.mdx +3 -0
  60. package/api-docs/variables/LIGHT_WRAP_TIGHTNESS.mdx +3 -0
  61. package/api-docs/variables/MASK_COMBINE_RATIO.mdx +1 -1
  62. package/api-docs/variables/MORPH_DILATE_RADIUS_PX.mdx +3 -0
  63. package/api-docs/variables/MORPH_ERODE_RADIUS_PX.mdx +3 -0
  64. package/api-docs/variables/MORPH_PASS.mdx +3 -0
  65. package/api-docs/variables/MediaStreamTrackTransferable.mdx +5 -0
  66. package/api-docs/variables/PERSON_CENTER.mdx +3 -0
  67. package/api-docs/variables/RENDERER_OPTIONS_STRUCT.mdx +3 -0
  68. package/api-docs/variables/SIGMA_RANGE.mdx +3 -0
  69. package/api-docs/variables/SIGMA_SPACE.mdx +3 -0
  70. package/api-docs/variables/STRONG_EDGE_BLUR_AMOUNT.mdx +3 -0
  71. package/api-docs/variables/cloneImageRecord.mdx +19 -0
  72. package/api-docs/variables/compareImageRecords.mdx +18 -0
  73. package/api-docs/variables/createRemoteImageBitmap.mdx +1 -1
  74. package/api-docs/variables/getCanvasRenderingContext2D.mdx +14 -0
  75. package/api-docs/variables/getImageSize.mdx +13 -0
  76. package/api-docs/variables/isRenderOptionsKey.mdx +13 -0
  77. package/api-docs/variables/isValidGpuAPI.mdx +13 -0
  78. package/dist/common/backends/webgl/binaryMask.d.ts +8 -0
  79. package/dist/common/backends/webgl/binaryMask.js +95 -0
  80. package/dist/common/backends/webgl/blender.d.ts +2 -1
  81. package/dist/common/backends/webgl/blender.js +18 -15
  82. package/dist/common/backends/webgl/blur.d.ts +1 -1
  83. package/dist/common/backends/webgl/blur.js +23 -16
  84. package/dist/common/backends/webgl/canvas.js +9 -4
  85. package/dist/common/backends/webgl/diffAbsMask.d.ts +10 -0
  86. package/dist/common/backends/webgl/diffAbsMask.js +103 -0
  87. package/dist/common/backends/webgl/geodesicReconstruction.d.ts +13 -0
  88. package/dist/common/backends/webgl/geodesicReconstruction.js +176 -0
  89. package/dist/common/backends/webgl/jointBilateralFilter.d.ts +12 -0
  90. package/dist/common/backends/webgl/jointBilateralFilter.js +108 -0
  91. package/dist/common/backends/webgl/morphErode.d.ts +13 -0
  92. package/dist/common/backends/webgl/morphErode.js +121 -0
  93. package/dist/common/backends/webgl/renderer.js +194 -44
  94. package/dist/common/backends/webgl/replace.d.ts +17 -0
  95. package/dist/common/backends/webgl/replace.js +126 -0
  96. package/dist/common/backends/webgl/selectComponent.d.ts +15 -0
  97. package/dist/common/backends/webgl/selectComponent.js +102 -0
  98. package/dist/common/backends/webgl/smoothingMask.d.ts +3 -3
  99. package/dist/common/backends/webgl/smoothingMask.js +22 -21
  100. package/dist/common/backends/webgl/tentBlur.d.ts +9 -0
  101. package/dist/common/backends/webgl/tentBlur.js +118 -0
  102. package/dist/common/backends/webgl/texture.d.ts +2 -3
  103. package/dist/common/backends/webgl/texture.js +21 -19
  104. package/dist/common/backends/webgl/textureToTexture.d.ts +1 -1
  105. package/dist/common/backends/webgl/textureToTexture.js +19 -16
  106. package/dist/common/backends/webgl/webglUtils.d.ts +7 -1
  107. package/dist/common/backends/webgl/webglUtils.js +72 -10
  108. package/dist/common/backends/webgpu/blender.d.ts +6 -1
  109. package/dist/common/backends/webgpu/blender.js +96 -51
  110. package/dist/common/backends/webgpu/constants.js +1 -1
  111. package/dist/common/backends/webgpu/dualFilterBlur.d.ts +2 -3
  112. package/dist/common/backends/webgpu/dualFilterBlur.js +146 -140
  113. package/dist/common/backends/webgpu/jointBilateralFilter.d.ts +7 -0
  114. package/dist/common/backends/webgpu/jointBilateralFilter.js +162 -0
  115. package/dist/common/backends/webgpu/renderer.js +205 -43
  116. package/dist/common/backends/webgpu/replace.d.ts +11 -0
  117. package/dist/common/backends/webgpu/replace.js +175 -0
  118. package/dist/common/backends/webgpu/resize.d.ts +4 -0
  119. package/dist/common/backends/webgpu/resize.js +76 -0
  120. package/dist/common/backends/webgpu/smoothingMask.d.ts +2 -2
  121. package/dist/common/backends/webgpu/smoothingMask.js +74 -40
  122. package/dist/common/backends/webgpu/tentBlur.d.ts +5 -0
  123. package/dist/common/backends/webgpu/tentBlur.js +131 -0
  124. package/dist/common/backends/webgpu/texture.d.ts +2 -3
  125. package/dist/common/backends/webgpu/texture.js +29 -20
  126. package/dist/common/backends/webgpu/textureToTexture.d.ts +1 -1
  127. package/dist/common/backends/webgpu/textureToTexture.js +28 -15
  128. package/dist/common/backends/webgpu/types.d.ts +2 -0
  129. package/dist/common/backends/webgpu/webgpuUtils.d.ts +24 -4
  130. package/dist/common/backends/webgpu/webgpuUtils.js +60 -11
  131. package/dist/common/constants.d.ts +22 -5
  132. package/dist/common/constants.js +23 -5
  133. package/dist/common/index.d.ts +2 -0
  134. package/dist/common/index.js +2 -0
  135. package/dist/common/tsconfig.tsbuildinfo +1 -1
  136. package/dist/common/typeGuards.d.ts +2 -0
  137. package/dist/common/typeGuards.js +7 -0
  138. package/dist/common/types/media.d.ts +5 -1
  139. package/dist/common/types/messageEvents.d.ts +31 -4
  140. package/dist/common/types/processor.d.ts +6 -4
  141. package/dist/common/types/render.d.ts +147 -15
  142. package/dist/common/types/render.js +23 -1
  143. package/dist/common/types/segmentation.d.ts +0 -12
  144. package/dist/common/types/utils.d.ts +21 -0
  145. package/dist/common/utils.d.ts +29 -2
  146. package/dist/common/utils.js +206 -10
  147. package/dist/main/audio.js +3 -3
  148. package/dist/main/benchUtils.d.ts +35 -3
  149. package/dist/main/benchUtils.js +149 -15
  150. package/dist/main/index.d.ts +1 -1
  151. package/dist/main/index.js +1 -1
  152. package/dist/main/tsconfig.tsbuildinfo +1 -1
  153. package/dist/main/types.d.ts +0 -6
  154. package/dist/main/utils.d.ts +4 -0
  155. package/dist/main/utils.js +31 -0
  156. package/dist/main/video/constants.d.ts +1 -4
  157. package/dist/main/video/constants.js +1 -5
  158. package/dist/main/video/index.d.ts +3 -4
  159. package/dist/main/video/index.js +3 -4
  160. package/dist/main/video/inputProcessAdaptor.d.ts +30 -0
  161. package/dist/main/video/inputProcessAdaptor.js +198 -0
  162. package/dist/main/video/segmenter.d.ts +35 -0
  163. package/dist/main/video/{segmenters/mediapipe.js → segmenter.js} +93 -53
  164. package/dist/main/video/typeGuards.d.ts +2 -0
  165. package/dist/main/video/typeGuards.js +8 -1
  166. package/dist/main/video/types.d.ts +36 -16
  167. package/dist/main/video/utils.d.ts +5 -4
  168. package/dist/main/video/utils.js +49 -44
  169. package/dist/main/video/video.d.ts +29 -7
  170. package/dist/main/video/video.js +323 -28
  171. package/dist/workers/mediaWorker.js +35 -162
  172. package/dist/workers/tsconfig.tsbuildinfo +1 -1
  173. package/dist/worklets/tsconfig.tsbuildinfo +1 -1
  174. package/package.json +13 -12
  175. package/api-docs/functions/createCanvasTransform.mdx +0 -14
  176. package/api-docs/functions/createVideoTrackProcessor.mdx +0 -9
  177. package/api-docs/functions/createVideoTrackProcessorWithFallback.mdx +0 -15
  178. package/api-docs/interfaces/Detector.mdx +0 -81
  179. package/api-docs/interfaces/SegmentationParams.mdx +0 -18
  180. package/api-docs/interfaces/Transform.mdx +0 -62
  181. package/api-docs/type-aliases/ProcessVideoTrack.mdx +0 -15
  182. package/api-docs/type-aliases/SegmentationTransform.mdx +0 -3
  183. package/dist/common/backends/webgl/shaders/blendFragmentShader.d.ts +0 -1
  184. package/dist/common/backends/webgl/shaders/blendFragmentShader.js +0 -21
  185. package/dist/common/backends/webgl/shaders/dualFilterBlurFragmentShader.d.ts +0 -1
  186. package/dist/common/backends/webgl/shaders/dualFilterBlurFragmentShader.js +0 -45
  187. package/dist/common/backends/webgl/shaders/smoothingMaskFragmentShader.d.ts +0 -1
  188. package/dist/common/backends/webgl/shaders/smoothingMaskFragmentShader.js +0 -57
  189. package/dist/common/backends/webgl/shaders/textureFragmentShader.d.ts +0 -1
  190. package/dist/common/backends/webgl/shaders/textureFragmentShader.js +0 -16
  191. package/dist/common/backends/webgl/shaders/vertexShader.d.ts +0 -1
  192. package/dist/common/backends/webgl/shaders/vertexShader.js +0 -19
  193. package/dist/main/transformer.d.ts +0 -1
  194. package/dist/main/transformer.js +0 -4
  195. package/dist/main/video/canvasTransform.d.ts +0 -17
  196. package/dist/main/video/canvasTransform.js +0 -253
  197. package/dist/main/video/segmenters/mediapipe.d.ts +0 -22
  198. package/dist/main/video/transformer.d.ts +0 -9
  199. package/dist/main/video/transformer.js +0 -68
  200. package/dist/main/video/videoStreamTrackProcessor.d.ts +0 -20
  201. package/dist/main/video/videoStreamTrackProcessor.js +0 -86
@@ -0,0 +1,118 @@
1
+ import { assert } from '@pexip/utils';
2
+ import { m3 } from '../../m3';
3
+ import { RENDERING_EVENTS } from '../../constants';
4
+ import { clamping } from '../../utils';
5
+ import { createGLProgram, createMaskTexture, createFrameBuffer, } from './webglUtils';
6
+ import vertexSrc from './shaders/matrix.vert';
7
+ import fragmentSrc from './shaders/tentBlur.frag';
8
+ const MAX_RADIUS_PX = 16;
9
+ const clampRadiusPx = clamping(0, MAX_RADIUS_PX);
10
+ /**
11
+ * Create a tent blur renderer for small radius blurring of a mask.
12
+ * The blur is implemented as a separable filter.
13
+ */
14
+ export const createTentBlurRenderer = (processor, width, height) => {
15
+ const { gl, program, attribLocations, uniformLocations, floatSingleChannelSupported, floatFullChannelSupported, release, } = createGLProgram(processor, {
16
+ attribs: {
17
+ position: 'a_position',
18
+ texCoord: 'a_texCoord',
19
+ },
20
+ uniforms: {
21
+ matrix: 'u_matrix',
22
+ mask: 'u_mask',
23
+ texelSize: 'u_texel_size',
24
+ direction: 'u_direction',
25
+ radiusPx: 'u_radius_px',
26
+ },
27
+ vertexSrc,
28
+ fragmentSrc,
29
+ });
30
+ const vao = gl.createVertexArray();
31
+ gl.bindVertexArray(vao);
32
+ // Position
33
+ const positionBuffer = gl.createBuffer();
34
+ gl.enableVertexAttribArray(attribLocations.position);
35
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
36
+ gl.vertexAttribPointer(attribLocations.position, 2, gl.FLOAT, false, 0, 0);
37
+ gl.bufferData(gl.ARRAY_BUFFER,
38
+ // prettier-ignore
39
+ new Float32Array([
40
+ 0, 0,
41
+ 0, 1,
42
+ 1, 0,
43
+ 1, 0,
44
+ 0, 1,
45
+ 1, 1,
46
+ ]), gl.STATIC_DRAW);
47
+ // Texture coordinates for the rectangle
48
+ const texCoordBuffer = gl.createBuffer();
49
+ gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
50
+ gl.bufferData(gl.ARRAY_BUFFER,
51
+ // prettier-ignore
52
+ new Float32Array([
53
+ 0, 0,
54
+ 0, 1,
55
+ 1, 0,
56
+ 1, 0,
57
+ 0, 1,
58
+ 1, 1,
59
+ ]), gl.STATIC_DRAW);
60
+ gl.enableVertexAttribArray(attribLocations.texCoord);
61
+ gl.vertexAttribPointer(attribLocations.texCoord, 2, gl.FLOAT, false, 0, 0);
62
+ const outputTexturePing = createMaskTexture(gl, width, height, false, floatSingleChannelSupported, floatFullChannelSupported);
63
+ const frameBufferPing = createFrameBuffer(gl, outputTexturePing);
64
+ const outputTexturePong = createMaskTexture(gl, width, height, false, floatSingleChannelSupported, floatFullChannelSupported);
65
+ const frameBufferPong = createFrameBuffer(gl, outputTexturePong);
66
+ const scaleFactor = processor.width / width;
67
+ return {
68
+ render: (mask, radiusPx) => {
69
+ assert(!gl.isContextLost(), RENDERING_EVENTS.ContextLost);
70
+ gl.clearColor(0, 0, 0, 0);
71
+ gl.clear(gl.COLOR_BUFFER_BIT);
72
+ gl.useProgram(program);
73
+ gl.bindVertexArray(vao);
74
+ gl.uniform2f(uniformLocations.texelSize, 1 / mask.width, 1 / mask.height);
75
+ gl.uniform1i(uniformLocations.radiusPx, clampRadiusPx(Math.floor(radiusPx / scaleFactor)));
76
+ const matrix = m3.projection(1, 1, 1);
77
+ // No Flip Y Coordinate for drawing on the frame buffer
78
+ // Project, position and scale to full-size of the canvas
79
+ gl.uniformMatrix3fv(uniformLocations.matrix, false, matrix);
80
+ let write = frameBufferPing;
81
+ let read = mask.texture;
82
+ // Ping-pong framebuffers for multiple passes
83
+ // Separable
84
+ for (let j = 0; j < 2; j++) {
85
+ // Textures
86
+ gl.activeTexture(gl.TEXTURE0);
87
+ gl.uniform1i(uniformLocations.mask, 0);
88
+ gl.bindTexture(gl.TEXTURE_2D, read);
89
+ // Horizontal then Vertical
90
+ gl.uniform2f(uniformLocations.direction, 1.0 - j, 0.0 + j);
91
+ gl.bindFramebuffer(gl.FRAMEBUFFER, write);
92
+ gl.viewport(0, 0, mask.width, mask.height);
93
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
94
+ // Swap
95
+ [read, write] =
96
+ write === frameBufferPing
97
+ ? [outputTexturePing, frameBufferPong]
98
+ : [outputTexturePong, frameBufferPing];
99
+ }
100
+ // Cleanup
101
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
102
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
103
+ gl.bindTexture(gl.TEXTURE_2D, null);
104
+ gl.bindVertexArray(null);
105
+ return { texture: read, width, height };
106
+ },
107
+ release: () => {
108
+ gl.deleteBuffer(positionBuffer);
109
+ gl.deleteBuffer(texCoordBuffer);
110
+ gl.deleteTexture(outputTexturePing);
111
+ gl.deleteTexture(outputTexturePong);
112
+ gl.deleteFramebuffer(frameBufferPing);
113
+ gl.deleteFramebuffer(frameBufferPong);
114
+ gl.deleteVertexArray(vao);
115
+ release();
116
+ },
117
+ };
118
+ };
@@ -1,9 +1,8 @@
1
- import type { VideoFrameLike } from '../../types/media';
2
1
  import type { TextureInfo } from './types';
3
2
  /**
4
3
  * Render Video frame into texture
5
4
  */
6
- export declare const createTextureRenderer: (processor: OffscreenCanvas) => {
7
- render: (video: VideoFrameLike) => TextureInfo;
5
+ export declare const createTextureRenderer: (processor: OffscreenCanvas, redOnly: boolean) => {
6
+ render: (frame: VideoFrame | ImageBitmap | OffscreenCanvas) => TextureInfo;
8
7
  release: () => void;
9
8
  };
@@ -1,14 +1,14 @@
1
1
  import { assert } from '@pexip/utils';
2
2
  import { RENDERING_EVENTS } from '../../constants';
3
3
  import { m3 } from '../../m3';
4
- import { createAndSetupTexture, createGLProgram } from './webglUtils';
5
- import { vertexShaderSource } from './shaders/vertexShader';
6
- import { textureFragmentShaderSource } from './shaders/textureFragmentShader';
4
+ import { createFrameBuffer, createGLProgram, createMaskTexture, createRGBAFrameTexture, } from './webglUtils';
5
+ import vertexSrc from './shaders/matrix.vert';
6
+ import fragmentSrc from './shaders/texture.frag';
7
7
  /**
8
8
  * Render Video frame into texture
9
9
  */
10
- export const createTextureRenderer = (processor) => {
11
- const { gl, program, attribLocations, uniformLocations, release } = createGLProgram(processor, {
10
+ export const createTextureRenderer = (processor, redOnly) => {
11
+ const { gl, program, attribLocations, uniformLocations, floatFullChannelSupported, floatSingleChannelSupported, release, } = createGLProgram(processor, {
12
12
  attribs: {
13
13
  position: 'a_position',
14
14
  texCoord: 'a_texCoord',
@@ -17,8 +17,8 @@ export const createTextureRenderer = (processor) => {
17
17
  matrix: 'u_matrix',
18
18
  texture: 'u_texture',
19
19
  },
20
- vertexSrc: vertexShaderSource,
21
- fragmentSrc: textureFragmentShaderSource,
20
+ vertexSrc,
21
+ fragmentSrc,
22
22
  });
23
23
  const vao = gl.createVertexArray();
24
24
  gl.bindVertexArray(vao);
@@ -53,14 +53,13 @@ export const createTextureRenderer = (processor) => {
53
53
  ]), gl.STATIC_DRAW);
54
54
  gl.enableVertexAttribArray(attribLocations.texCoord);
55
55
  gl.vertexAttribPointer(attribLocations.texCoord, 2, gl.FLOAT, false, 0, 0);
56
- const frameTexture = createAndSetupTexture(gl);
57
- const outputTexture = createAndSetupTexture(gl);
58
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, processor.width, processor.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
59
- const frameBuffer = gl.createFramebuffer();
60
- gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
61
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0);
56
+ const frameTexture = createRGBAFrameTexture(gl, processor.width, processor.height, true, floatFullChannelSupported);
57
+ const outputTexture = redOnly
58
+ ? createMaskTexture(gl, processor.width, processor.height, false, floatSingleChannelSupported, floatFullChannelSupported)
59
+ : createRGBAFrameTexture(gl, processor.width, processor.height, true, floatFullChannelSupported);
60
+ const frameBuffer = createFrameBuffer(gl, outputTexture);
62
61
  return {
63
- render: (video) => {
62
+ render: (frame) => {
64
63
  assert(!gl.isContextLost(), RENDERING_EVENTS.ContextLost);
65
64
  // Draw on the frame buffer
66
65
  gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
@@ -71,16 +70,19 @@ export const createTextureRenderer = (processor) => {
71
70
  gl.bindVertexArray(vao);
72
71
  // Texture Unit setup
73
72
  gl.uniform1i(uniformLocations.texture, 0);
74
- // Project, position and scale to full-size of the canvas
73
+ // Project, position, and scale to full-size of the canvas
75
74
  const matrix = m3.projection(1, 1, 1);
76
75
  gl.uniformMatrix3fv(uniformLocations.matrix, false, matrix);
77
- // Frame texture
76
+ // Upload the frame to texture
78
77
  gl.activeTexture(gl.TEXTURE0);
79
78
  gl.bindTexture(gl.TEXTURE_2D, frameTexture);
80
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video.frame);
81
- gl.generateMipmap(gl.TEXTURE_2D);
79
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, frame);
82
80
  gl.drawArrays(gl.TRIANGLES, 0, 6);
83
- assert(outputTexture);
81
+ // Cleanup
82
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
83
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
84
+ gl.bindTexture(gl.TEXTURE_2D, null);
85
+ gl.bindVertexArray(null);
84
86
  return {
85
87
  texture: outputTexture,
86
88
  width: processor.width,
@@ -2,7 +2,7 @@ import type { TextureInfo } from './types';
2
2
  /**
3
3
  * Render texture into another texture, i.e. clone
4
4
  */
5
- export declare const createTextureToTextureRenderer: (processor: OffscreenCanvas) => {
5
+ export declare const createTextureToTextureRenderer: (processor: OffscreenCanvas, redOnly: boolean, linearSampling?: boolean, targetWidth?: number, targetHeight?: number, float?: boolean) => {
6
6
  render: (inputTexture: TextureInfo) => TextureInfo;
7
7
  release: () => void;
8
8
  };
@@ -1,14 +1,14 @@
1
1
  import { assert } from '@pexip/utils';
2
2
  import { RENDERING_EVENTS } from '../../constants';
3
3
  import { m3 } from '../../m3';
4
- import { createAndSetupTexture, createGLProgram } from './webglUtils';
5
- import { vertexShaderSource } from './shaders/vertexShader';
6
- import { textureFragmentShaderSource } from './shaders/textureFragmentShader';
4
+ import { createFrameBuffer, createGLProgram, createMaskTexture, createRGBAFrameTexture, } from './webglUtils';
5
+ import vertexSrc from './shaders/matrix.vert';
6
+ import fragmentSrc from './shaders/texture.frag';
7
7
  /**
8
8
  * Render texture into another texture, i.e. clone
9
9
  */
10
- export const createTextureToTextureRenderer = (processor) => {
11
- const { gl, program, attribLocations, uniformLocations, release } = createGLProgram(processor, {
10
+ export const createTextureToTextureRenderer = (processor, redOnly, linearSampling = false, targetWidth = processor.width, targetHeight = processor.height, float = true) => {
11
+ const { gl, program, attribLocations, uniformLocations, floatFullChannelSupported, floatSingleChannelSupported, release, } = createGLProgram(processor, {
12
12
  attribs: {
13
13
  position: 'a_position',
14
14
  texCoord: 'a_texCoord',
@@ -17,8 +17,8 @@ export const createTextureToTextureRenderer = (processor) => {
17
17
  matrix: 'u_matrix',
18
18
  texture: 'u_texture',
19
19
  },
20
- vertexSrc: vertexShaderSource,
21
- fragmentSrc: textureFragmentShaderSource,
20
+ vertexSrc,
21
+ fragmentSrc,
22
22
  });
23
23
  const vao = gl.createVertexArray();
24
24
  gl.bindVertexArray(vao);
@@ -53,17 +53,16 @@ export const createTextureToTextureRenderer = (processor) => {
53
53
  ]), gl.STATIC_DRAW);
54
54
  gl.enableVertexAttribArray(attribLocations.texCoord);
55
55
  gl.vertexAttribPointer(attribLocations.texCoord, 2, gl.FLOAT, false, 0, 0);
56
- const outputTexture = createAndSetupTexture(gl);
57
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, processor.width, processor.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
58
- const frameBuffer = gl.createFramebuffer();
59
- gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
60
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0);
56
+ const outputTexture = redOnly
57
+ ? createMaskTexture(gl, targetWidth, targetHeight, linearSampling, float && floatSingleChannelSupported, float && floatFullChannelSupported)
58
+ : createRGBAFrameTexture(gl, targetWidth, targetHeight, linearSampling, float && floatFullChannelSupported);
59
+ const frameBuffer = createFrameBuffer(gl, outputTexture);
61
60
  return {
62
61
  render: (inputTexture) => {
63
62
  assert(!gl.isContextLost(), RENDERING_EVENTS.ContextLost);
64
63
  // Draw on the frame buffer
65
64
  gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
66
- gl.viewport(0, 0, processor.width, processor.height);
65
+ gl.viewport(0, 0, targetWidth, targetHeight);
67
66
  gl.clearColor(0, 0, 0, 1);
68
67
  gl.clear(gl.COLOR_BUFFER_BIT);
69
68
  gl.useProgram(program);
@@ -76,11 +75,15 @@ export const createTextureToTextureRenderer = (processor) => {
76
75
  const matrix = m3.projection(1, 1, 1);
77
76
  gl.uniformMatrix3fv(uniformLocations.matrix, false, matrix);
78
77
  gl.drawArrays(gl.TRIANGLES, 0, 6);
79
- assert(outputTexture);
78
+ // Cleanup
79
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
80
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
81
+ gl.bindTexture(gl.TEXTURE_2D, null);
82
+ gl.bindVertexArray(null);
80
83
  return {
81
84
  texture: outputTexture,
82
- width: processor.width,
83
- height: processor.height,
85
+ width: targetWidth,
86
+ height: targetHeight,
84
87
  };
85
88
  },
86
89
  release: () => {
@@ -61,7 +61,11 @@ export declare const createProgram: (gl: WebGLRenderingContext, shaders: [WebGLS
61
61
  * A parallel array to opt_attribs letting you assign locations.
62
62
  */
63
63
  export declare const createProgramFromSources: (gl: WebGLRenderingContext, [vs, fs]: [GLShaderSource, GLShaderSource], attribs?: string[], locations?: number[]) => [WebGLProgram, Release];
64
- export declare const createAndSetupTexture: (gl: WebGL2RenderingContext) => WebGLTexture;
64
+ export declare const createAndSetupTexture: (gl: WebGL2RenderingContext, linear: boolean) => WebGLTexture;
65
+ export declare const createRGBAFrameTexture: (gl: WebGL2RenderingContext, width: number, height: number, linear?: boolean, withFloat?: boolean) => WebGLTexture;
66
+ export declare const createMaskTexture: (gl: WebGL2RenderingContext, width: number, height: number, linear?: boolean, withFloatSingle?: boolean, withFloatFull?: boolean) => WebGLTexture;
67
+ export declare const createFrameBuffer: (gl: WebGL2RenderingContext, texture: WebGLTexture) => WebGLFramebuffer;
68
+ export declare const support: (gl: WebGL2RenderingContext, internalFormat: GLint, format: GLenum, width?: number, height?: number) => boolean;
65
69
  type Location<S extends string> = S extends `u_${string}` ? ReturnType<WebGL2RenderingContext['getUniformLocation']> : S extends `a_${string}` ? ReturnType<WebGL2RenderingContext['getAttribLocation']> : never;
66
70
  export declare const getLocations: <T extends Record<string, string>>(gl: WebGL2RenderingContext, program: WebGLProgram, locations: T) => { [Key in keyof T]: Location<T[Key]>; };
67
71
  export declare const createGLProgram: <A extends Record<string, string>, U extends Record<string, string>>(processCanvas: OffscreenCanvas, { attribs, uniforms, vertexSrc, fragmentSrc, }: {
@@ -75,6 +79,8 @@ export declare const createGLProgram: <A extends Record<string, string>, U exten
75
79
  attribLocations: { [Key in keyof A]: Location<A[Key]>; };
76
80
  uniformLocations: { [Key_1 in keyof U]: Location<U[Key_1]>; };
77
81
  release: Release;
82
+ floatSingleChannelSupported: boolean;
83
+ floatFullChannelSupported: boolean;
78
84
  };
79
85
  export declare const toTextureInfo: (mask: MPMask) => TextureInfo;
80
86
  export {};
@@ -1,3 +1,5 @@
1
+ import { assert } from '@pexip/utils';
2
+ import { RENDERING_EVENTS } from '../../constants';
1
3
  /**
2
4
  * WebGL Shader type enum
3
5
  */
@@ -90,6 +92,7 @@ export const loadShader = (gl, shaderType, shaderSource) => {
90
92
  */
91
93
  export const createProgram = (gl, shaders, attribs, locations) => {
92
94
  const program = gl.createProgram();
95
+ let released = false;
93
96
  if (!program) {
94
97
  throw new Error('Unable to create WebGL program');
95
98
  }
@@ -118,11 +121,14 @@ export const createProgram = (gl, shaders, attribs, locations) => {
118
121
  return [
119
122
  program,
120
123
  () => {
121
- for (const shader of shaders) {
122
- gl.detachShader(program, shader);
123
- gl.deleteShader(shader);
124
+ if (!released) {
125
+ released = true;
126
+ for (const shader of shaders) {
127
+ gl.detachShader(program, shader);
128
+ gl.deleteShader(shader);
129
+ }
130
+ gl.deleteProgram(program);
124
131
  }
125
- gl.deleteProgram(program);
126
132
  },
127
133
  ];
128
134
  };
@@ -139,16 +145,69 @@ export const createProgramFromSources = (gl, [vs, fs], attribs, locations) => cr
139
145
  loadShader(gl, GL_SHADER_TYPE.VertexShader, vs),
140
146
  loadShader(gl, GL_SHADER_TYPE.FragmentShader, fs),
141
147
  ], attribs, locations);
142
- export const createAndSetupTexture = (gl) => {
148
+ export const createAndSetupTexture = (gl, linear) => {
143
149
  const texture = gl.createTexture();
144
150
  gl.bindTexture(gl.TEXTURE_2D, texture);
145
- // Set the parameters so we don't need mips and so we're not filtering
151
+ // Set the parameters so we don't need MIPS and so we're not filtering
146
152
  // and we don't repeat at the edges.
147
153
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
148
154
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
155
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR : gl.NEAREST);
156
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linear ? gl.LINEAR : gl.NEAREST);
157
+ return texture;
158
+ };
159
+ export const createRGBAFrameTexture = (gl, width, height, linear = false, withFloat = false) => {
160
+ const texture = createAndSetupTexture(gl, linear);
161
+ if (withFloat) {
162
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA16F, width, height, 0, gl.RGBA, gl.HALF_FLOAT, null);
163
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
164
+ return texture;
165
+ }
166
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
167
+ gl.bindTexture(gl.TEXTURE_2D, null);
168
+ return texture;
169
+ };
170
+ export const createMaskTexture = (gl, width, height, linear = false, withFloatSingle = false, withFloatFull = false) => {
171
+ const texture = createAndSetupTexture(gl, linear);
172
+ if (withFloatSingle) {
173
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R16F, width, height, 0, gl.RED, gl.HALF_FLOAT, null);
174
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
175
+ return texture;
176
+ }
177
+ if (withFloatFull) {
178
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA16F, width, height, 0, gl.RGBA, gl.HALF_FLOAT, null);
179
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
180
+ return texture;
181
+ }
182
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, width, height, 0, gl.RED, gl.UNSIGNED_BYTE, null);
183
+ gl.bindTexture(gl.TEXTURE_2D, null);
184
+ return texture;
185
+ };
186
+ export const createFrameBuffer = (gl, texture) => {
187
+ const frameBuffer = gl.createFramebuffer();
188
+ gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
189
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
190
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
191
+ return frameBuffer;
192
+ };
193
+ export const support = (gl, internalFormat, format, width = 2, height = 2) => {
194
+ // Create single-channel float16 texture
195
+ const tex = gl.createTexture();
196
+ gl.bindTexture(gl.TEXTURE_2D, tex);
197
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, width, height, 0, format, gl.HALF_FLOAT, null);
149
198
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
150
199
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
151
- return texture;
200
+ // Attach texture
201
+ const fb = createFrameBuffer(gl, tex);
202
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
203
+ // Check completeness
204
+ const complete = gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE;
205
+ // Clean up
206
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
207
+ gl.deleteFramebuffer(fb);
208
+ gl.bindTexture(gl.TEXTURE_2D, null);
209
+ gl.deleteTexture(tex);
210
+ return complete;
152
211
  };
153
212
  export const getLocations = (gl, program, locations) => Object.keys(locations).reduce((acc, key) => {
154
213
  const k = key;
@@ -167,9 +226,7 @@ export const createGLProgram = (processCanvas, { attribs, uniforms, vertexSrc, f
167
226
  premultipliedAlpha: false,
168
227
  powerPreference: 'high-performance',
169
228
  });
170
- if (!gl) {
171
- throw new Error('WebGL2 is not supported');
172
- }
229
+ assert(gl, RENDERING_EVENTS.ContextCreationError);
173
230
  gl.enable(gl.BLEND);
174
231
  gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
175
232
  assertShaderSource(vertexSrc);
@@ -178,12 +235,17 @@ export const createGLProgram = (processCanvas, { attribs, uniforms, vertexSrc, f
178
235
  vertexSrc,
179
236
  fragmentSrc,
180
237
  ]);
238
+ const hasFloat = !!gl.getExtension('EXT_color_buffer_float');
239
+ const floatSingleChannelSupported = hasFloat && support(gl, gl.R16F, gl.RED);
240
+ const floatFullChannelSupported = hasFloat && support(gl, gl.RGBA16F, gl.RGBA);
181
241
  return {
182
242
  gl,
183
243
  program,
184
244
  attribLocations: getLocations(gl, program, attribs),
185
245
  uniformLocations: getLocations(gl, program, uniforms),
186
246
  release,
247
+ floatSingleChannelSupported,
248
+ floatFullChannelSupported,
187
249
  };
188
250
  };
189
251
  export const toTextureInfo = (mask) => ({
@@ -1,8 +1,13 @@
1
+ import type { RendererOptions } from '../../types/render';
1
2
  /**
2
3
  *
3
4
  * Blend foreground and background according to the mask
4
5
  */
5
6
  export declare const createBlendRenderer: (processor: OffscreenCanvas, device: GPUDevice, presentationFormat: GPUTextureFormat, isContextLost: () => boolean) => {
6
- render: (frameTexture: GPUTexture, bgTexture: GPUTexture, maskTexture: GPUTexture) => void;
7
+ render: (encoder: GPUCommandEncoder, { foreground, background, mask, }: {
8
+ foreground: GPUTexture;
9
+ background: GPUTexture;
10
+ mask: GPUTexture;
11
+ }, options: RendererOptions) => void;
7
12
  release: () => void;
8
13
  };
@@ -1,7 +1,7 @@
1
+ import { makeShaderDataDefinitions, makeStructuredView } from 'webgpu-utils';
1
2
  import { assert } from '@pexip/utils';
2
3
  import { RENDERING_EVENTS } from '../../constants';
3
4
  import blenderShader from './shaders/blenderShader.wgsl';
4
- import { RENDER_PASS_COLOR_ATTACHMENT_CLEAR_VALUE } from './constants';
5
5
  /**
6
6
  *
7
7
  * Blend foreground and background according to the mask
@@ -16,63 +16,108 @@ export const createBlendRenderer = (processor, device, presentationFormat, isCon
16
16
  format: presentationFormat,
17
17
  alphaMode: 'premultiplied',
18
18
  });
19
+ const defs = makeShaderDataDefinitions(blenderShader);
20
+ // @ts-expect-error This is what we get from the API
21
+ const uniforms = makeStructuredView(defs.uniforms.thresholds);
22
+ // Cache shader module and pipeline at init time
23
+ const shaderModule = device.createShaderModule({
24
+ label: 'blender shader',
25
+ code: blenderShader,
26
+ });
27
+ const pipeline = device.createRenderPipeline({
28
+ label: 'blender pipeline',
29
+ layout: 'auto',
30
+ vertex: {
31
+ module: shaderModule,
32
+ },
33
+ fragment: {
34
+ module: shaderModule,
35
+ targets: [{ format: presentationFormat }],
36
+ },
37
+ });
38
+ // Cache sampler at init time
39
+ const linearSampler = device.createSampler({
40
+ addressModeU: 'clamp-to-edge',
41
+ addressModeV: 'clamp-to-edge',
42
+ magFilter: 'linear',
43
+ minFilter: 'linear',
44
+ });
45
+ const nearestSampler = device.createSampler({
46
+ addressModeU: 'clamp-to-edge',
47
+ addressModeV: 'clamp-to-edge',
48
+ magFilter: 'nearest',
49
+ minFilter: 'nearest',
50
+ });
51
+ const uniformsBuffer = device.createBuffer({
52
+ size: uniforms.arrayBuffer.byteLength,
53
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
54
+ });
55
+ const updateUniforms = (options) => {
56
+ uniforms.set({
57
+ background: options.backgroundThreshold,
58
+ foreground: options.foregroundThreshold,
59
+ });
60
+ // Upload to GPU
61
+ device.queue.writeBuffer(uniformsBuffer, 0, uniforms.arrayBuffer);
62
+ };
63
+ const colorAttachment0 = {
64
+ loadOp: 'load',
65
+ storeOp: 'store',
66
+ };
67
+ const renderPassDescriptor = {
68
+ label: 'blender renderPass',
69
+ colorAttachments: [colorAttachment0],
70
+ };
71
+ const bindGroup0 = device.createBindGroup({
72
+ layout: pipeline.getBindGroupLayout(0),
73
+ entries: [
74
+ { binding: 0, resource: linearSampler },
75
+ { binding: 1, resource: nearestSampler },
76
+ { binding: 2, resource: { buffer: uniformsBuffer } },
77
+ ],
78
+ });
79
+ let cachedBindGroup1 = null;
80
+ let cachedMask = null;
81
+ let cachedBackground = null;
82
+ let cachedForeground = null;
83
+ let cachedBackgroundThreshold = -1;
84
+ let cachedForegroundThreshold = -1;
19
85
  return {
20
- render: (frameTexture, bgTexture, maskTexture) => {
86
+ render: (encoder, { foreground, background, mask, }, options) => {
21
87
  assert(!isContextLost(), RENDERING_EVENTS.ContextLost);
22
- const pipeline = device.createRenderPipeline({
23
- label: 'blender pipeline',
24
- layout: 'auto',
25
- vertex: {
26
- module: device.createShaderModule({
27
- label: 'blender vertex',
28
- code: blenderShader,
29
- }),
30
- },
31
- fragment: {
32
- module: device.createShaderModule({
33
- label: 'blender fragment',
34
- code: blenderShader,
35
- }),
36
- targets: [{ format: presentationFormat }],
37
- },
38
- });
39
- const encoder = device.createCommandEncoder({
40
- label: 'blender encoder',
41
- });
42
- const pass = encoder.beginRenderPass({
43
- label: 'blender renderPass',
44
- colorAttachments: [
45
- {
46
- view: context.getCurrentTexture().createView(),
47
- clearValue: RENDER_PASS_COLOR_ATTACHMENT_CLEAR_VALUE,
48
- loadOp: 'clear',
49
- storeOp: 'store',
50
- },
51
- ],
52
- });
88
+ colorAttachment0.view = context.getCurrentTexture().createView();
89
+ if (!(cachedBackground === background &&
90
+ cachedForeground === foreground &&
91
+ cachedMask === mask)) {
92
+ cachedBindGroup1 = device.createBindGroup({
93
+ layout: pipeline.getBindGroupLayout(1),
94
+ entries: [
95
+ { binding: 0, resource: background.createView() },
96
+ { binding: 1, resource: foreground.createView() },
97
+ { binding: 2, resource: mask.createView() },
98
+ ],
99
+ });
100
+ cachedBackground = background;
101
+ cachedForeground = foreground;
102
+ cachedMask = mask;
103
+ }
104
+ if (!(cachedBackgroundThreshold === options.backgroundThreshold &&
105
+ cachedForegroundThreshold === options.foregroundThreshold)) {
106
+ updateUniforms(options);
107
+ cachedBackgroundThreshold = options.backgroundThreshold;
108
+ cachedForegroundThreshold = options.foregroundThreshold;
109
+ }
110
+ const pass = encoder.beginRenderPass(renderPassDescriptor);
53
111
  pass.setPipeline(pipeline);
54
- const sampler = device.createSampler({
55
- addressModeU: 'repeat',
56
- addressModeV: 'repeat',
57
- magFilter: 'nearest',
58
- });
59
- const bindGroup = device.createBindGroup({
60
- layout: pipeline.getBindGroupLayout(0),
61
- entries: [
62
- { binding: 0, resource: sampler },
63
- { binding: 1, resource: bgTexture.createView() },
64
- { binding: 2, resource: frameTexture.createView() },
65
- { binding: 3, resource: maskTexture.createView() },
66
- ],
67
- });
68
- pass.setBindGroup(0, bindGroup);
112
+ pass.setBindGroup(0, bindGroup0);
113
+ pass.setBindGroup(1, cachedBindGroup1);
69
114
  pass.draw(6); // call our vertex shader 6 times
70
115
  pass.end();
71
- const commandBuffer = encoder.finish();
72
- device.queue.submit([commandBuffer]);
73
116
  },
74
117
  release: () => {
75
- // Nothing
118
+ uniformsBuffer.destroy();
119
+ cachedBackgroundThreshold = -1;
120
+ cachedForegroundThreshold = -1;
76
121
  },
77
122
  };
78
123
  };
@@ -1 +1 @@
1
- export const RENDER_PASS_COLOR_ATTACHMENT_CLEAR_VALUE = [0.0, 0.0, 0.0, 0];
1
+ export const RENDER_PASS_COLOR_ATTACHMENT_CLEAR_VALUE = [0.0, 0.0, 0.0, 1.0];
@@ -1,5 +1,4 @@
1
- import type { VideoFrameLike } from '../../types/media';
2
- export declare const createBlurRenderer: (processor: OffscreenCanvas, device: GPUDevice, presentationFormat: GPUTextureFormat, isContextLost: () => boolean) => {
3
- render: (frame: VideoFrameLike, pass: number) => GPUTexture;
1
+ export declare const createBlurRenderer: (device: GPUDevice, width: number, height: number, textureFormat: GPUTextureFormat, isContextLost: () => boolean) => {
2
+ render: (encoder: GPUCommandEncoder, frame: GPUTexture, pass: number) => GPUTexture;
4
3
  release: () => void;
5
4
  };