我正在开发一个WebGL应用程序,从HTML5视频流中获取纹理,使用HLS.js。在桌面上运行良好,并且在移动Android上的1920 * 1080视频上也能正常工作,但无法处理3840 * 2160的视频。
我已经在一些高端设备(Xperia X Performance、Samsung Galaxy S8)上测试了该应用程序,但这两种设备都无法播放4K视频。
我知道这些设备可以播放视频,因为我还有一个调试模式,在该模式下,视频元素附加到DOM上,视频渲染完美。
我还在这些设备上使用了http://webglreport.com/,该页面显示我应该能够使用4096 * 4096的纹理。
我还手动使用JavaScript ArrayBuffer生成了一个3840 * 2160的纹理,而且该纹理被正确渲染了。
以下是我复制视频的方法
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, this.videoElement);
当在Chrome Android上执行大小为3840 * 2160的视频调用时,我会得到以下日志打印:
SurfaceUtils: set up nativeWindow 0xc9ef2008 for 3840x2160, color 0x7fa30c04, rotation 0, usage 0x20002900 chromium: [INFO:CONSOLE(11818)] "WebGL: INVALID_VALUE: texImage2D: width or height out of range"
这对应于gl.getError()的错误代码:
GL_INVALID_VALUE,0x0501
这些是我用于支持纹理的参数。
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
以下是我生成和上传测试纹理的方法
const width = 3840;
const height = 2160;
const generateTex = (w: number, h: number): number[] => {
const res = [];
for (let i = 0; i < w * h; i++) {
res.push(0, 255, 0);
}
return res;
};
const image = new Uint8Array(generateTex(width, height));
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, width, height, 0, gl.RGB, gl.UNSIGNED_BYTE, image);
texImage2D
的文档表示:
源类型为HTMLVideoElement
纹理的宽度和高度设置为上传的视频帧的宽度和高度(以像素为单位)。
问题是:是否有规范可以解释为什么我的3840 * 2160纹理无法被渲染?
简而言之:
- 更高端的设备(Xperia X Performance,Galaxy S8)
- Android Chrome
- 我可以上传大小为3840 * 2160的自定义纹理并进行渲染
- 我可以使用
<video>
标签解码和播放大小为3840 * 2160的视频 - 我无法将3840 * 2160视频的帧上传到WebGL中
- 低分辨率可以正常工作
谢谢!