Fix CRT shader: use hwupload=derive_device=opencl for writable output pool
program_opencl inherits its output hw_frames_ctx from the input link.
When the input came via hwmap:mode=read, the inherited context creates
CL_MEM_READ_ONLY images for output - kernel writes are silently
discarded, producing black frames ('kein video').
Fix: download to CPU, then hwupload=derive_device=opencl to create a
fresh writable OpenCL context before program_opencl. Matches Jellyfin's
existing iHD doOclTonemap pattern (GetVaapiVidFiltersPrefered:5711).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4925,28 +4925,41 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
if (IsCrtShaderEnabled(state))
|
||||
{
|
||||
// VAAPI → OpenCL → CRT (NV12) → VAAPI (reverse=1) → QSV.
|
||||
// Shader now works in NV12 throughout (no scale_opencl format break),
|
||||
// so program_opencl output stays in the VAAPI-linked OpenCL pool.
|
||||
// reverse=1 to VAAPI mirrors the doOclTonemap+isVaInVaOut path.
|
||||
mainFilters.Add("hwmap=derive_device=opencl:mode=read");
|
||||
// VAAPI → CPU → OpenCL (writable) → CRT (NV12) → CPU → QSV.
|
||||
// program_opencl inherits the hw frames context from its input link.
|
||||
// If that context was created via hwmap:mode=read, the output images are
|
||||
// CL_MEM_READ_ONLY and kernel writes are silently discarded (black output).
|
||||
// Solution: hwdownload+hwupload=derive_device=opencl creates a fresh
|
||||
// writable OpenCL context, matching Jellyfin's iHD doOclTonemap pattern.
|
||||
mainFilters.Add("hwdownload");
|
||||
mainFilters.Add("format=nv12");
|
||||
mainFilters.Add("hwupload=derive_device=opencl");
|
||||
mainFilters.AddRange(GetCrtShaderOclFilters(state));
|
||||
mainFilters.Add("hwmap=derive_device=vaapi:mode=write:reverse=1");
|
||||
mainFilters.Add("format=vaapi");
|
||||
mainFilters.Add("hwdownload");
|
||||
mainFilters.Add("format=nv12");
|
||||
mainFilters.Add("hwupload");
|
||||
mainFilters.Add("format=qsv");
|
||||
}
|
||||
|
||||
// VAAPI → QSV (zero-copy, shared libva surface) [both paths]
|
||||
else
|
||||
{
|
||||
// VAAPI → QSV (zero-copy, shared libva surface)
|
||||
mainFilters.Add("hwmap=derive_device=qsv");
|
||||
mainFilters.Add("format=qsv");
|
||||
}
|
||||
}
|
||||
else if (isQsvDecoder)
|
||||
{
|
||||
if (IsCrtShaderEnabled(state))
|
||||
{
|
||||
// QSV → OpenCL → CRT → QSV (reverse=1)
|
||||
mainFilters.Add("hwmap=derive_device=opencl:mode=read");
|
||||
// QSV → CPU → OpenCL (writable) → CRT (NV12) → CPU → QSV.
|
||||
// Same reason as isVaapiDecoder: avoid read-only output pool.
|
||||
mainFilters.Add("hwdownload");
|
||||
mainFilters.Add("format=nv12");
|
||||
mainFilters.Add("hwupload=derive_device=opencl");
|
||||
mainFilters.AddRange(GetCrtShaderOclFilters(state));
|
||||
mainFilters.Add("hwmap=derive_device=qsv:mode=write:reverse=1:extra_hw_frames=16");
|
||||
mainFilters.Add("hwdownload");
|
||||
mainFilters.Add("format=nv12");
|
||||
mainFilters.Add("hwupload");
|
||||
mainFilters.Add("format=qsv");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user