player: fix HEVC color (BT.709 limited range)
The built-in WASM player (frontend/static/vendor/hevcjs/hevc-core.js) rendered washed-out, green/red-shifted video. Two causes, both fixed: - VideoFrame path (Chrome): the I420 VideoFrame was created without a colorSpace, so the browser defaulted to BT.601 limited -> hue shift, and guessed the range -> washout. Set explicit BT.709, fullRange:false. - WebGL fallback shader: used BT.709 FULL-range coefficients on limited-range camera output -> washout/desaturation. Switched to BT.709 limited-range conversion ((Y-16)*255/219, chroma centered 128). VERSION -> 0.0.116. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+12
-7
@@ -286,7 +286,11 @@ var FrameRenderer = class _FrameRenderer {
|
|||||||
format: "I420",
|
format: "I420",
|
||||||
codedWidth: w,
|
codedWidth: w,
|
||||||
codedHeight: h,
|
codedHeight: h,
|
||||||
timestamp
|
timestamp,
|
||||||
|
// Hikvision H.265 — BT.709, TV/limited range. Без явного colorSpace браузер для
|
||||||
|
// I420 по умолчанию берёт BT.601 (зелёно-красный сдвиг) и неверный диапазон
|
||||||
|
// (белёсость). Задаём явно, чтобы YUV→RGB шёл по правильной матрице и диапазону.
|
||||||
|
colorSpace: { primaries: "bt709", transfer: "bt709", matrix: "bt709", fullRange: false }
|
||||||
});
|
});
|
||||||
await this._writer.write(videoFrame);
|
await this._writer.write(videoFrame);
|
||||||
videoFrame.close();
|
videoFrame.close();
|
||||||
@@ -394,12 +398,13 @@ var FRAGMENT_SRC = `
|
|||||||
uniform sampler2D u_texCb;
|
uniform sampler2D u_texCb;
|
||||||
uniform sampler2D u_texCr;
|
uniform sampler2D u_texCr;
|
||||||
void main() {
|
void main() {
|
||||||
float y = texture2D(u_texY, v_tex).r;
|
// BT.709 limited range (TV): Y∈[16,235]/255 → (Y-16)*255/219; Cb/Cr∈[16,240]/255 центр 128/255.
|
||||||
float cb = texture2D(u_texCb, v_tex).r - 0.5;
|
float y = (texture2D(u_texY, v_tex).r - 0.0627451) * 1.1643836;
|
||||||
float cr = texture2D(u_texCr, v_tex).r - 0.5;
|
float cb = texture2D(u_texCb, v_tex).r - 0.5019608;
|
||||||
float r = y + 1.5748 * cr;
|
float cr = texture2D(u_texCr, v_tex).r - 0.5019608;
|
||||||
float g = y - 0.1873 * cb - 0.4681 * cr;
|
float r = y + 1.7927411 * cr;
|
||||||
float b = y + 1.8556 * cb;
|
float g = y - 0.2132486 * cb - 0.5329093 * cr;
|
||||||
|
float b = y + 2.1124018 * cb;
|
||||||
gl_FragColor = vec4(clamp(r, 0.0, 1.0), clamp(g, 0.0, 1.0), clamp(b, 0.0, 1.0), 1.0);
|
gl_FragColor = vec4(clamp(r, 0.0, 1.0), clamp(g, 0.0, 1.0), clamp(b, 0.0, 1.0), 1.0);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user