Skip to content

Commit a377169

Browse files
committed
feat: support alpha buffer
1 parent d0098c1 commit a377169

File tree

8 files changed

+269
-135
lines changed

8 files changed

+269
-135
lines changed

.eslintrc

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
"WebGLTexture": false,
9191
"WebGLBuffer": false,
9292
"WebGLProgram": false,
93+
"WebGLUniformLocation": false,
9394
"HTMLCanvasElement": false,
9495
"ResizeObserver": false,
9596
"name": false,

example/src/renderer/examples/advanced/VirtualBackground/VirtualBackground.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ export default class VirtualBackground
7979
true
8080
);
8181

82+
this.engine.setParameters(
83+
JSON.stringify({ 'rtc.video.send_alpha_data': true })
84+
);
85+
8286
// Need to enable video on this case
8387
// If you only call `enableAudio`, only relay the audio stream to the target channel
8488
this.engine.enableVideo();

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
"yuv-canvas": "1.2.6"
137137
},
138138
"agora_electron": {
139-
"iris_sdk_win": "https://download.agora.io/sdk/release/iris_4.2.6-build.3_DCG_Windows_Video_20231116_0243.zip",
140-
"iris_sdk_mac": "https://download.agora.io/sdk/release/iris_4.2.6-build.3_DCG_Mac_Video_20231116_0243.zip"
139+
"iris_sdk_win": "https://download.agora.io/sdk/release/iris_4.2.6.1-dev.2_DCG_Windows_Video_20231204_0548.zip",
140+
"iris_sdk_mac": "https://download.agora.io/sdk/release/iris_4.2.6.1-dev.2_DCG_Mac_Video_20231204_0548.zip"
141141
}
142142
}

patches/yuv-canvas+1.2.6.patch

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
diff --git a/node_modules/yuv-canvas/src/SoftwareFrameSink.js b/node_modules/yuv-canvas/src/SoftwareFrameSink.js
2+
index 9627638..cff283c
3+
--- a/node_modules/yuv-canvas/src/SoftwareFrameSink.js
4+
+++ b/node_modules/yuv-canvas/src/SoftwareFrameSink.js
5+
@@ -41,11 +41,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6+
imageData = ctx.createImageData(width, height);
7+
8+
// Prefill the alpha to opaque
9+
- var data = imageData.data,
10+
- pixelCount = width * height * 4;
11+
- for (var i = 0; i < pixelCount; i += 4) {
12+
- data[i + 3] = 255;
13+
- }
14+
+ // var data = imageData.data,
15+
+ // pixelCount = width * height * 4;
16+
+ // for (var i = 0; i < pixelCount; i += 4) {
17+
+ // data[i + 3] = 255;
18+
+ // }
19+
}
20+
21+
function initResampleCanvas(cropWidth, cropHeight) {
22+
diff --git a/node_modules/yuv-canvas/src/YCbCr.js b/node_modules/yuv-canvas/src/YCbCr.js
23+
index 1e15c37..e51abe1
24+
--- a/node_modules/yuv-canvas/src/YCbCr.js
25+
+++ b/node_modules/yuv-canvas/src/YCbCr.js
26+
@@ -78,24 +78,28 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27+
output[outPtr0 ] = (multY + multCrR) >> 8;
28+
output[outPtr0 + 1] = (multY - multCbCrG) >> 8;
29+
output[outPtr0 + 2] = (multY + multCbB) >> 8;
30+
+ output[outPtr0 + 3] = buffer.a ? buffer.a[outPtr0 / 4] : 255;
31+
outPtr0 += 4;
32+
33+
multY = 298 * bytesY[Y0Ptr++] | 0;
34+
output[outPtr0 ] = (multY + multCrR) >> 8;
35+
output[outPtr0 + 1] = (multY - multCbCrG) >> 8;
36+
output[outPtr0 + 2] = (multY + multCbB) >> 8;
37+
+ output[outPtr0 + 3] = buffer.a ? buffer.a[outPtr0 / 4] : 255;
38+
outPtr0 += 4;
39+
40+
multY = 298 * bytesY[Y1Ptr++] | 0;
41+
output[outPtr1 ] = (multY + multCrR) >> 8;
42+
output[outPtr1 + 1] = (multY - multCbCrG) >> 8;
43+
output[outPtr1 + 2] = (multY + multCbB) >> 8;
44+
+ output[outPtr1 + 3] = buffer.a ? buffer.a[outPtr1 / 4] : 255;
45+
outPtr1 += 4;
46+
47+
multY = 298 * bytesY[Y1Ptr++] | 0;
48+
output[outPtr1 ] = (multY + multCrR) >> 8;
49+
output[outPtr1 + 1] = (multY - multCbCrG) >> 8;
50+
output[outPtr1 + 2] = (multY + multCbB) >> 8;
51+
+ output[outPtr1 + 3] = buffer.a ? buffer.a[outPtr1 / 4] : 255;
52+
outPtr1 += 4;
53+
}
54+
outPtr0 += outStride;
55+
@@ -127,6 +131,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56+
output[outPtr ] = (multY + multCrR) >> 8;
57+
output[outPtr + 1] = (multY - multCbCrG) >> 8;
58+
output[outPtr + 2] = (multY + multCbB) >> 8;
59+
+ output[outPtr + 3] = buffer.a ? buffer.a[outPtr / 4] : 255;
60+
outPtr += 4;
61+
}
62+
}

source_code/agora_node_ext/agora_electron_bridge.cpp

+20-7
Original file line numberDiff line numberDiff line change
@@ -387,17 +387,20 @@ napi_value AgoraElectronBridge::GetVideoFrame(napi_env env,
387387

388388
napi_value obj1 = args[1];
389389
napi_value y_buffer_obj;
390-
void *y_buffer;
391-
size_t y_length;
390+
void *y_buffer = nullptr;
391+
size_t y_length = 0;
392392
napi_value u_buffer_obj;
393-
void *u_buffer;
394-
size_t u_length;
393+
void *u_buffer = nullptr;
394+
size_t u_length = 0;
395395
napi_value v_buffer_obj;
396-
void *v_buffer;
397-
size_t v_length;
396+
void *v_buffer = nullptr;
397+
size_t v_length = 0;
398398
int width;
399399
int height;
400400
int yStride;
401+
napi_value alpha_buffer_obj;
402+
void *alpha_buffer = nullptr;
403+
size_t alpha_length = 0;
401404

402405
napi_obj_get_property(env, obj1, "yBuffer", y_buffer_obj);
403406
napi_get_buffer_info(env, y_buffer_obj, &y_buffer, &y_length);
@@ -412,6 +415,14 @@ napi_value AgoraElectronBridge::GetVideoFrame(napi_env env,
412415
napi_obj_get_property(env, obj1, "height", height);
413416
napi_obj_get_property(env, obj1, "yStride", yStride);
414417

418+
napi_obj_get_property(env, obj1, "alphaBuffer", alpha_buffer_obj);
419+
napi_value undefinedValue;
420+
napi_get_undefined(env, &undefinedValue);
421+
bool isUndefined;
422+
if (napi_strict_equals(env, alpha_buffer_obj, undefinedValue, &isUndefined) == napi_ok && !isUndefined) {
423+
napi_get_buffer_info(env, alpha_buffer_obj, &alpha_buffer, &alpha_length);
424+
}
425+
415426
IrisCVideoFrame videoFrame;
416427
videoFrame.yBuffer = (uint8_t *) y_buffer;
417428
videoFrame.uBuffer = (uint8_t *) u_buffer;
@@ -421,7 +432,8 @@ napi_value AgoraElectronBridge::GetVideoFrame(napi_env env,
421432
videoFrame.yStride = yStride;
422433
videoFrame.metadata_buffer = nullptr;
423434
videoFrame.metadata_size = 0;
424-
videoFrame.alphaBuffer = nullptr;
435+
videoFrame.alphaBuffer = (uint8_t *) alpha_buffer;
436+
videoFrame.hasAlphaBuffer = false;
425437

426438
bool isNewFrame = false;
427439
napi_value retObj;
@@ -451,6 +463,7 @@ napi_value AgoraElectronBridge::GetVideoFrame(napi_env env,
451463
napi_obj_set_property(env, obj1, "avsync_type", videoFrame.avsync_type);
452464
napi_obj_set_property(env, obj1, "metadata_size", videoFrame.metadata_size);
453465
// napi_obj_set_property(env, obj1, "textureId", videoFrame.textureId);
466+
napi_obj_set_property(env, obj1, "hasAlphaBuffer", videoFrame.hasAlphaBuffer);
454467

455468
return retObj;
456469
}

ts/Renderer/RendererCache.ts

+10
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@ export class RendererCache {
108108
return;
109109
}
110110

111+
if ((this.videoFrame as any).hasAlphaBuffer) {
112+
if (this.videoFrame.alphaBuffer === undefined) {
113+
this.videoFrame.alphaBuffer = Buffer.alloc(
114+
this.videoFrame.yStride! * this.videoFrame.height!
115+
);
116+
}
117+
} else {
118+
this.videoFrame.alphaBuffer = undefined;
119+
}
120+
111121
if (isNewFrame) {
112122
this.renderers.forEach((renderer) => {
113123
renderer.drawFrame(this.videoFrame);

0 commit comments

Comments
 (0)