Skip to content

Commit 0d339d3

Browse files
committed
fix(helper): NVENC scale_cuda filter syntax and NVDEC reference-frame pool
Two NVENC pipeline issues were dropping every Tubi-class (HEVC source) segment back to the software encoder fallback: scale_cuda filter chain. The previous filter string "scale_cuda=W:H:force_original_aspect_ratio=decrease,format=nv12" had a comma before format=nv12, so ffmpeg parsed it as two filters: scale_cuda (GPU surface output) followed by a standalone format=nv12 CPU-side filter. The auto_scale ffmpeg inserted to bridge GPU->CPU couldn't convert the surface and surfaced as "Impossible to convert between the formats supported by the filter 'Parsed_scale_cuda_0' and the filter 'auto_scale_0'". Move format inside scale_cuda's own options ("scale_cuda=w=W:h=H:format=nv12:force_original_aspect_ratio=decrease") so the whole filter stays on GPU and feeds h264_nvenc directly. NVDEC reference-frame pool. HEVC sources with longer reference chains than the default extra_hw_frames pool covers ("Could not find ref with POC N") would drop frames mid-decode and produce a short or empty segment that the upload validator then rejected. Bump -extra_hw_frames to 16 on the NVENC backend so the pool keeps the reference frames the decoder still needs.
1 parent c14563e commit 0d339d3

2 files changed

Lines changed: 15 additions & 3 deletions

File tree

src/WKVRCProxy.Tests/FfmpegHelperTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public void TranscodeWorkerProcess_BuildsSafeNvencSegmentCommand()
153153
Assert.Contains(command.Arguments, argument => argument.Contains("Mozilla/5.0 (Windows NT 10.0; Win64; x64)", StringComparison.Ordinal));
154154
Assert.Contains("h264_nvenc", command.Arguments);
155155
AssertHardwareDecodeBeforeInput(command.Arguments, "cuda", "cuda");
156-
Assert.Contains(command.Arguments, argument => argument.StartsWith("scale_cuda=1280:720:", StringComparison.Ordinal));
156+
Assert.Contains(command.Arguments, argument => argument.StartsWith("scale_cuda=w=1280:h=720:", StringComparison.Ordinal));
157157
Assert.Contains(command.Arguments, argument => argument.Contains("format=nv12", StringComparison.Ordinal));
158158
Assert.Contains("-force_key_frames", command.Arguments);
159159
Assert.Contains("-c:a", command.Arguments);

src/WKVRCProxy/Helper/TranscodeWorkerProcess.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,12 @@ private static IReadOnlyList<string> HardwareDecodeOptionsFor(HardwareEncoderCap
245245
{
246246
return encoder.Backend switch
247247
{
248-
HardwareEncoderBackend.Nvenc => new[] { "-hwaccel", "cuda", "-hwaccel_output_format", "cuda" },
248+
// -extra_hw_frames widens NVDEC's reference-frame pool. Some HEVC sources
249+
// (Tubi's catalog among them) use longer reference chains than the cuvid
250+
// default 25 covers and surface as "Could not find ref with POC N" decoder
251+
// warnings followed by a black/short segment. Bumping the pool stops the
252+
// decoder from dropping reference frames it still needs.
253+
HardwareEncoderBackend.Nvenc => new[] { "-hwaccel", "cuda", "-hwaccel_output_format", "cuda", "-extra_hw_frames", "16" },
249254
HardwareEncoderBackend.Qsv => new[] { "-hwaccel", "qsv", "-hwaccel_output_format", "qsv" },
250255
HardwareEncoderBackend.Amf or HardwareEncoderBackend.MediaFoundation =>
251256
new[] { "-hwaccel", "d3d11va", "-hwaccel_output_format", "d3d11" },
@@ -259,8 +264,15 @@ private static string HardwareScaleFilterFor(HardwareEncoderCapability encoder,
259264
string height = safeHeight.ToString(CultureInfo.InvariantCulture);
260265
return encoder.Backend switch
261266
{
267+
// `format=nv12` must be part of scale_cuda's option list (colon-
268+
// separated), not a separate filter. The previous form used a comma,
269+
// which made ffmpeg parse `format=nv12` as a standalone CPU-side
270+
// filter; an auto_scale would then be inserted to bridge the CUDA
271+
// surface from scale_cuda to the CPU format filter and fail with
272+
// "Impossible to convert between the formats supported by the
273+
// filter 'Parsed_scale_cuda_0' and the filter 'auto_scale_0'".
262274
HardwareEncoderBackend.Nvenc =>
263-
"scale_cuda=" + width + ":" + height + ":force_original_aspect_ratio=decrease,format=nv12",
275+
"scale_cuda=w=" + width + ":h=" + height + ":format=nv12:force_original_aspect_ratio=decrease",
264276
HardwareEncoderBackend.Qsv =>
265277
"scale_qsv=w=" + width + ":h=" + height + ":format=nv12",
266278
HardwareEncoderBackend.Amf or HardwareEncoderBackend.MediaFoundation =>

0 commit comments

Comments
 (0)