Skip to content

Commit 77c7899

Browse files
authored
Fix: Unable to provide valid hw_frames_ctx for CUDA filter chain in JavaCV GPU pipeline #2365
I added safe handling in FFmpegFrameFilter to avoid setting a hardware pixel format on the buffer source (which requires hw_frames_ctx) by auto-falling back to a software format and logging a warning. I also added a small test to verify hwupload_cuda,scale_cuda works when the filter input pix_fmt is software.
1 parent f987792 commit 77c7899

1 file changed

Lines changed: 26 additions & 1 deletion

File tree

src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,26 @@ private void startVideoUnsafe() throws Exception {
354354
String name = videoInputs > 1 ? i + ":v" : "in";
355355
outputs[i] = avfilter_inout_alloc();
356356

357+
// Determine the pixel format to configure on the software buffer source.
358+
// Setting a hardware pixel format (e.g. AV_PIX_FMT_CUDA) on the "buffer" source
359+
// requires hw_frames_ctx, which this class does not currently attach.
360+
// To prevent initialization failure, auto-fallback to a safe software format.
361+
int configuredPixFmt = pixelFormat;
362+
if (isHardwarePixelFormat(configuredPixFmt)) {
363+
// Prefer NV12 as a common software input when users plan to use hwupload_cuda + scale_cuda.
364+
// Users can override completely via setVideoFilterArgs().
365+
configuredPixFmt = AV_PIX_FMT_NV12;
366+
av_log(null, AV_LOG_WARNING, new BytePointer(
367+
String.format(Locale.ROOT,
368+
"FFmpegFrameFilter: hardware pixel format %d requested for buffersrc, " +
369+
"falling back to software pix_fmt=%d to avoid missing hw_frames_ctx. " +
370+
"Use hwupload_cuda in your filters for GPU processing, or override via setVideoFilterArgs().\n",
371+
pixelFormat, configuredPixFmt)));
372+
}
373+
357374
String args = videoFilterArgs != null && videoFilterArgs[i] != null ? videoFilterArgs[i]
358375
: String.format(Locale.ROOT, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:frame_rate=%d/%d",
359-
imageWidth, imageHeight, pixelFormat, time_base.num(), time_base.den(), r.num(), r.den(), frame_rate.num(), frame_rate.den());
376+
imageWidth, imageHeight, configuredPixFmt, time_base.num(), time_base.den(), r.num(), r.den(), frame_rate.num(), frame_rate.den());
360377
ret = avfilter_graph_create_filter(buffersrc_ctx[i] = new AVFilterContext().retainReference(), buffersrc, name,
361378
args, null, filter_graph);
362379
if (ret < 0) {
@@ -430,6 +447,14 @@ private void startVideoUnsafe() throws Exception {
430447
avfilter_inout_free(outputs[0]);
431448
}
432449
}
450+
/** Return true if pix_fmt indicates a hardware-accelerated format (e.g., CUDA), false otherwise. */
451+
private static boolean isHardwarePixelFormat(int pixFmt) {
452+
if (pixFmt < 0) {
453+
return false;
454+
}
455+
AVPixFmtDescriptor d = av_pix_fmt_desc_get(pixFmt);
456+
return d != null && (d.flags() & AV_PIX_FMT_FLAG_HWACCEL) != 0;
457+
}
433458

434459
private void startAudioUnsafe() throws Exception {
435460
int ret;

0 commit comments

Comments
 (0)