2023-03-25 08:37:51 +08:00
|
|
|
|
2023-04-02 01:51:36 +08:00
|
|
|
/* mat4 to mat3:
|
|
|
|
mat3 coeff = mat3(
|
|
|
|
colorTransform[0].x, colorTransform[0].y, colorTransform[0].z,
|
|
|
|
colorTransform[1].x, colorTransform[1].y, colorTransform[1].z,
|
|
|
|
colorTransform[2].x, colorTransform[2].y, colorTransform[2].z
|
|
|
|
);
|
|
|
|
mat3 coeff = mat3(
|
|
|
|
colorTransform[0].xyz,
|
|
|
|
colorTransform[1].xyz,
|
|
|
|
colorTransform[2].xyz
|
|
|
|
);
|
|
|
|
mat3 coeff = mat3(colorTransform); // require GLES3
|
2023-03-25 08:37:51 +08:00
|
|
|
*/
|
|
|
|
|
2023-04-02 01:51:36 +08:00
|
|
|
// refer to:
|
|
|
|
// https://docs.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering#yuy2
|
2023-07-07 04:05:56 +08:00
|
|
|
const char* videoTextureYUY2_frag = R"(
|
2023-04-02 01:51:36 +08:00
|
|
|
|
2023-03-25 08:37:51 +08:00
|
|
|
#ifdef GL_ES
|
|
|
|
varying lowp vec4 v_fragmentColor;
|
|
|
|
varying mediump vec2 v_texCoord;
|
|
|
|
#else
|
|
|
|
varying vec4 v_fragmentColor;
|
|
|
|
varying vec2 v_texCoord;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
uniform sampler2D u_tex0; // Y sample
|
|
|
|
uniform sampler2D u_tex1; // UV sample
|
2023-04-02 01:51:36 +08:00
|
|
|
uniform mat4 colorTransform;
|
2023-03-25 08:37:51 +08:00
|
|
|
|
2023-04-02 01:51:36 +08:00
|
|
|
vec3 trasnformYUV(vec3 YUV)
|
2023-03-25 08:37:51 +08:00
|
|
|
{
|
2023-04-02 01:51:36 +08:00
|
|
|
YUV -= vec3(colorTransform[0].w, colorTransform[1].w, colorTransform[2].w);
|
|
|
|
return mat3(
|
|
|
|
colorTransform[0].xyz,
|
|
|
|
colorTransform[1].xyz,
|
|
|
|
colorTransform[2].xyz
|
|
|
|
) * YUV;
|
2023-03-25 08:37:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void main()
|
|
|
|
{
|
|
|
|
vec3 YUV;
|
|
|
|
|
2023-04-02 01:51:36 +08:00
|
|
|
/* For dual sampler */
|
|
|
|
YUV.yz = texture2D(u_tex1, v_texCoord).yw;
|
|
|
|
YUV.x = texture2D(u_tex0, v_texCoord).x;
|
|
|
|
|
2023-03-25 08:37:51 +08:00
|
|
|
/* Convert YUV to RGB */
|
|
|
|
vec4 OutColor;
|
2023-04-02 01:51:36 +08:00
|
|
|
OutColor.xyz = trasnformYUV(YUV);
|
2023-03-25 08:37:51 +08:00
|
|
|
OutColor.w = 1.0;
|
|
|
|
|
|
|
|
gl_FragColor = v_fragmentColor * OutColor;
|
|
|
|
}
|
2023-07-07 04:05:56 +08:00
|
|
|
)";
|
2023-03-25 08:37:51 +08:00
|
|
|
|
2023-04-02 01:51:36 +08:00
|
|
|
/*
|
|
|
|
The NV12 pixel format render shader:
|
|
|
|
- Windows:
|
|
|
|
- video format: HEVC(H256)
|
|
|
|
- support codec id: 'hev1', 'hvc1'
|
|
|
|
- Apple(macOS,iOS,tvOS):
|
|
|
|
- video format: H264,HEVC(H256)
|
|
|
|
- support codec id: 'hvc1'
|
|
|
|
- sub pixel formats:
|
|
|
|
- 'y420v'(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)
|
|
|
|
- 'y420f'(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)
|
|
|
|
Consider test videos:
|
|
|
|
- HEVC(H265): 1912x1080.mp4, 1920x1080.mp4, 1912x1080_hvc1.mp4
|
|
|
|
- H264: 1912x1080.mp4, 1920x1080.mp4, 1280x720.mp4, 432x240.mp4
|
|
|
|
refer to:
|
|
|
|
- https://docs.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering#nv12
|
|
|
|
- https://github.com/doyoulikerock/D3D11NV12Rendering/blob/master/D3D11NV12Rendering/PixelShader.hlsl
|
|
|
|
*/
|
2023-07-07 04:05:56 +08:00
|
|
|
const char* videoTextureNV12_frag = R"(
|
2023-03-25 08:37:51 +08:00
|
|
|
|
|
|
|
#ifdef GL_ES
|
|
|
|
varying lowp vec4 v_fragmentColor;
|
|
|
|
varying mediump vec2 v_texCoord;
|
|
|
|
#else
|
|
|
|
varying vec4 v_fragmentColor;
|
|
|
|
varying vec2 v_texCoord;
|
|
|
|
#endif
|
|
|
|
|
2023-04-02 01:51:36 +08:00
|
|
|
uniform sampler2D u_tex0; // Y sample: LumaTexture
|
|
|
|
uniform sampler2D u_tex1; // UV sample: ChromaTexture
|
|
|
|
uniform mat4 colorTransform;
|
2023-03-25 08:37:51 +08:00
|
|
|
|
2023-04-02 01:51:36 +08:00
|
|
|
vec3 trasnformYUV(vec3 YUV)
|
2023-03-25 08:37:51 +08:00
|
|
|
{
|
2023-04-02 01:51:36 +08:00
|
|
|
YUV -= vec3(colorTransform[0].w, colorTransform[1].w, colorTransform[2].w);
|
|
|
|
return mat3(
|
|
|
|
colorTransform[0].xyz,
|
|
|
|
colorTransform[1].xyz,
|
|
|
|
colorTransform[2].xyz
|
|
|
|
) * YUV;
|
2023-03-25 08:37:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void main()
|
|
|
|
{
|
|
|
|
vec3 YUV;
|
|
|
|
|
2023-04-02 01:51:36 +08:00
|
|
|
YUV.x = texture2D(u_tex0, v_texCoord).w; // Y
|
|
|
|
YUV.yz = texture2D(u_tex1, v_texCoord).xy; // CbCr
|
2023-03-25 08:37:51 +08:00
|
|
|
|
|
|
|
/* Convert YUV to RGB */
|
|
|
|
vec4 OutColor;
|
2023-04-02 01:51:36 +08:00
|
|
|
OutColor.xyz = trasnformYUV(YUV);
|
2023-03-25 08:37:51 +08:00
|
|
|
OutColor.w = 1.0;
|
|
|
|
|
|
|
|
gl_FragColor = v_fragmentColor * OutColor;
|
|
|
|
}
|
2023-07-07 04:05:56 +08:00
|
|
|
)";
|
2023-03-25 08:37:51 +08:00
|
|
|
|
2023-07-07 04:05:56 +08:00
|
|
|
const char* videoTextureBGRA_frag = R"(
|
2023-03-25 08:37:51 +08:00
|
|
|
#ifdef GL_ES
|
|
|
|
varying lowp vec4 v_fragmentColor;
|
|
|
|
varying mediump vec2 v_texCoord;
|
|
|
|
#else
|
|
|
|
varying vec4 v_fragmentColor;
|
|
|
|
varying vec2 v_texCoord;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
uniform sampler2D u_tex0;
|
|
|
|
|
|
|
|
void main()
|
|
|
|
{
|
|
|
|
gl_FragColor = v_fragmentColor * texture2D(u_tex0, v_texCoord).bgra;
|
|
|
|
}
|
2023-07-07 04:05:56 +08:00
|
|
|
)";
|