Skip to content

Commit 1579a49

Browse files
committed
feat: adapt colorspace for Android
1 parent 17577fc commit 1579a49

File tree

1 file changed

+88
-10
lines changed

1 file changed

+88
-10
lines changed

android/src/main/cpp/iris_rtc_rendering_android.cc

Lines changed: 88 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <jni.h>
1313
#include <memory>
1414
#include <vector>
15+
#include <cstring>
1516

1617
namespace agora {
1718
namespace iris {
@@ -508,6 +509,11 @@ class YUVRendering final : public RenderingOp {
508509
uTextureLoc_ = glGetUniformLocation(program, "uTexture");
509510
vTextureLoc_ = glGetUniformLocation(program, "vTexture");
510511

512+
// Get locations for ColorSpace uniforms
513+
colorMatrixLoc_ = glGetUniformLocation(program, "uColorMatrix");
514+
rangeLoc_ = glGetUniformLocation(program, "uRange");
515+
transferLoc_ = glGetUniformLocation(program, "uTransfer");
516+
511517
glGenTextures(3, texs_);
512518
CHECK_GL_ERROR()
513519
}
@@ -618,6 +624,52 @@ class YUVRendering final : public RenderingOp {
618624
GL_LUMINANCE, GL_UNSIGNED_BYTE, vBuffer);
619625
CHECK_GL_ERROR()
620626

627+
// Update color space uniforms if available
628+
if (colorMatrixLoc_ != -1) {
629+
float bt709[9] = {
630+
1.0f, 1.0f, 1.0f,
631+
0.0f, -0.39465f, 2.03211f,
632+
1.13983f, -0.58060f, 0.0f
633+
};
634+
float bt2020[9] = {
635+
1.0f, 1.0f, 1.0f,
636+
0.0f, -0.16455f, 1.88140f,
637+
1.47460f, -0.57135f, 0.0f
638+
};
639+
float smpte170m[9] = {
640+
1.0f, 1.0f, 1.0f,
641+
0.0f, -0.39173f, 2.01700f,
642+
1.59580f, -0.81290f, 0.0f
643+
};
644+
645+
float mat[9];
646+
int matrixId = (int)video_frame->colorSpace.matrix;
647+
switch (matrixId) {
648+
case agora::media::base::ColorSpace::MATRIXID_BT2020_NCL:
649+
memcpy(mat, bt2020, sizeof(mat));
650+
break;
651+
case agora::media::base::ColorSpace::MATRIXID_SMPTE170M:
652+
memcpy(mat, smpte170m, sizeof(mat));
653+
break;
654+
case agora::media::base::ColorSpace::MATRIXID_BT709:
655+
default:
656+
memcpy(mat, bt709, sizeof(mat));
657+
break;
658+
}
659+
glUniformMatrix3fv(colorMatrixLoc_, 1, GL_FALSE, mat);
660+
}
661+
662+
// 2. Set Range
663+
if (rangeLoc_ != -1) {
664+
int rangeVal = (video_frame->colorSpace.range == agora::media::base::ColorSpace::RANGEID_LIMITED) ? 1 : 0;
665+
glUniform1i(rangeLoc_, rangeVal);
666+
}
667+
668+
// 3. Set Transfer Function
669+
if (transferLoc_ != -1) {
670+
glUniform1i(transferLoc_, (int)video_frame->colorSpace.transfer);
671+
}
672+
621673
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
622674
CHECK_GL_ERROR()
623675

@@ -642,8 +694,8 @@ class YUVRendering final : public RenderingOp {
642694
"attribute vec2 aTextCoord;\n"
643695
"varying vec2 vTextCoord;\n"
644696
"void main() {\n"
645-
" vTextCoord = vec2(aTextCoord.x, 1.0 - aTextCoord.y);\n"
646-
" gl_Position = aPosition;\n"
697+
" gl_Position = aPosition;\n"
698+
" vTextCoord = aTextCoord;\n"
647699
"}\n";
648700

649701
const char *frag_shader_yuv_ =
@@ -652,15 +704,38 @@ class YUVRendering final : public RenderingOp {
652704
"uniform sampler2D yTexture;\n"
653705
"uniform sampler2D uTexture;\n"
654706
"uniform sampler2D vTexture;\n"
707+
"uniform mat3 uColorMatrix;\n"
708+
"uniform int uRange;\n"
709+
"uniform int uTransfer;\n"
710+
"\n"
711+
"vec3 applyTransfer(vec3 c, int transferId) {\n"
712+
" if (transferId == 8) { return c; }\n" // LINEAR
713+
" else if (transferId == 4) { return pow(c, vec3(1.0/2.2)); }\n" // GAMMA22
714+
" else if (transferId == 5) { return pow(c, vec3(1.0/2.8)); }\n" // GAMMA28
715+
" else if (transferId == 1) { return pow(c, vec3(1.0/2.4)); }\n" // BT709 approx
716+
" return c;\n"
717+
"}\n"
718+
"\n"
655719
"void main() {\n"
656-
" vec3 yuv;\n"
657-
" vec3 rgb;\n"
658-
" yuv.r = texture2D(yTexture, vTextCoord).r;\n"
659-
" yuv.g = texture2D(uTexture, vTextCoord).r - 0.5;\n"
660-
" yuv.b = texture2D(vTexture, vTextCoord).r - 0.5;\n"
661-
" rgb = mat3(1.0, 1.0, 1.0, 0.0, -0.39465, 2.03211, 1.13983, "
662-
"-0.58060, 0.0) * yuv;\n"
663-
" gl_FragColor = vec4(rgb, 1.0);\n"
720+
" float y = texture2D(yTexture, vTextCoord).r;\n"
721+
" float u = texture2D(uTexture, vTextCoord).r - 0.5;\n"
722+
" float v = texture2D(vTexture, vTextCoord).r - 0.5;\n"
723+
"\n"
724+
" // 1. Range Conversion\n"
725+
" if (uRange == 1) { // Limited Range to Full Range\n"
726+
" y = (y - 16.0/255.0) * (255.0/219.0);\n"
727+
" u = u * (224.0/255.0);\n"
728+
" v = v * (224.0/255.0);\n"
729+
" }\n"
730+
"\n"
731+
" // 2. YUV to RGB Conversion with dynamic matrix\n"
732+
" vec3 yuv = vec3(y, u, v);\n"
733+
" vec3 rgb = uColorMatrix * yuv;\n"
734+
"\n"
735+
" // 3. Apply Transfer Function (Gamma Correction)\n"
736+
" rgb = applyTransfer(rgb, uTransfer);\n"
737+
"\n"
738+
" gl_FragColor = vec4(clamp(rgb, 0.0, 1.0), 1.0);\n"
664739
"}\n";
665740

666741
// clang-format off
@@ -680,6 +755,9 @@ class YUVRendering final : public RenderingOp {
680755
GLint yTextureLoc_;
681756
GLint uTextureLoc_;
682757
GLint vTextureLoc_;
758+
GLint colorMatrixLoc_ = -1;
759+
GLint rangeLoc_ = -1;
760+
GLint transferLoc_ = -1;
683761

684762
std::unique_ptr<ScopedShader> shader_;
685763
};

0 commit comments

Comments
 (0)