1212#include < jni.h>
1313#include < memory>
1414#include < vector>
15+ #include < cstring>
1516
1617namespace agora {
1718namespace 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