PR #23367 opened by Edison Ling (edisonling)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23367
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23367.patch

Add parameter `constrained_intra_pred` for users to enable constrained intra 
prediction (as opposed to default unconstrained) in D3D12 H264 and HEVC 
encoding.

Usage:
  false (default): `-constrained_intra_pred false`  or  
`-constrained_intra_pred 0`
  true:                `-constrained_intra_pred true`   or  
`-constrained_intra_pred 1`

Sample command line:
```
ffmpeg.exe -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v 
h264_d3d12va -constrained_intra_pred true -y output.mp4
ffmpeg.exe -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v 
hevc_d3d12va -constrained_intra_pred true -y output.mp4
```
### Purpose
Constrained intra prediction restricts intra-coded blocks to only reference 
neighbouring blocks that were also intra-coded. Neighbours that were 
inter-predicted from another frame can no longer be used, preventing 
inter-predicted regions/blocks from bleeding to adjacent intra blocks.

Useful for error resilience to prevent spreading temporal error propagation to 
other regions during streaming and live broadcasting.

### Testing
PPS `constrained_intra_pred_flag` verified and output size and content verified.
- **AMD (RX 7600M & RX 9070):** H264 and HEVC both correct. 
`constrained_intra_pred_flag` is `0` when off/default and `1` when enabled, and 
size changes as expected. Tiny +/- file size difference, and slight quality 
drop when enabled.
- **Intel (Arc B580):** driver does not advertise H264 constrained-intra 
support, so the soft-fallback is exercised. `"Constrained intra prediction is 
not supported by the driver, disabling."` is logged, the flag stays `0`, and 
encoding completes normally. (HEVC is supported and verified, H264 was not able 
to be tested due to issues with base DX12 encoding)
- **NVIDIA (RTX 5070 Ti):** not tested. D3D12 hardware encoding is not working 
for me (fails regardless of `-constrained_intra_pred` setting, as well as with 
official FFmpeg 8.1.1), so the feature could not be tested.


_D3D12 AV1 encoding API has no constrained-intra-prediction flag_


>From 11972491aeaa8c7ad002782db2b844ba76bb9c22 Mon Sep 17 00:00:00 2001
From: "Ling, Edison" <[email protected]>
Date: Fri, 5 Jun 2026 10:04:23 -0400
Subject: [PATCH] avcodec/d3d12va_encode: Add H264/HEVC constrained intra
 prediction parameter support

Add parameter `constrained_intra_pred` for users to enable constrained intra 
prediction (as opposed to default unconstrained) in D3D12 H264 and HEVC 
encoding.

Usage:
  false (default): `-constrained_intra_pred false`  or  
`-constrained_intra_pred 0`
  true:            `-constrained_intra_pred true`   or  
`-constrained_intra_pred 1`

Sample command line:
```
ffmpeg.exe -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v 
h264_d3d12va -constrained_intra_pred true -y output.mp4
ffmpeg.exe -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v 
hevc_d3d12va -constrained_intra_pred true -y output.mp4
```
---
 libavcodec/d3d12va_encode_h264.c | 15 +++++++++++++++
 libavcodec/d3d12va_encode_hevc.c | 16 ++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/libavcodec/d3d12va_encode_h264.c b/libavcodec/d3d12va_encode_h264.c
index 47c6953d1b..55ed249064 100644
--- a/libavcodec/d3d12va_encode_h264.c
+++ b/libavcodec/d3d12va_encode_h264.c
@@ -45,6 +45,7 @@ typedef struct D3D12VAEncodeH264Context {
     int profile;
     int level;
     int deblock;
+    int constrained_intra_pred;
     int idr_pic_id;
 
     // Writer structures.
@@ -258,6 +259,7 @@ static int 
d3d12va_encode_h264_init_sequence_params(AVCodecContext *avctx)
     sps->log2_max_frame_num_minus4 = FFMAX(av_ceil_log2(base_ctx->gop_size) - 
4, 0);
     ctx->gop.pH264GroupOfPictures->log2_max_frame_num_minus4 = 
sps->log2_max_frame_num_minus4;
     pps->deblocking_filter_control_present_flag = 1;
+    pps->constrained_intra_pred_flag = priv->constrained_intra_pred;
 
     return 0;
 }
@@ -321,6 +323,16 @@ static int 
d3d12va_encode_h264_get_encoder_caps(AVCodecContext *avctx)
         }
     }
 
+    // Constrained intra prediction configuration
+    if (priv->constrained_intra_pred) {
+        if (h264_caps.SupportFlags & 
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264_FLAG_CONSTRAINED_INTRAPREDICTION_SUPPORT)
 {
+            config->ConfigurationFlags |= 
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_FLAG_USE_CONSTRAINED_INTRAPREDICTION;
+        } else {
+            av_log(avctx, AV_LOG_WARNING, "Constrained intra prediction is not 
supported by the driver, disabling.\n");
+            priv->constrained_intra_pred = 0;
+        }
+    }
+
     base_ctx->surface_width  = FFALIGN(avctx->width,  16);
     base_ctx->surface_height = FFALIGN(avctx->height, 16);
 
@@ -653,6 +665,9 @@ static const AVOption d3d12va_encode_h264_options[] = {
         { "cavlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, 
FLAGS, "coder" },
         { "cabac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, 
FLAGS, "coder" },
 
+    { "constrained_intra_pred", "Constrained intra prediction 
(constrained_intra_pred_flag)",
+      OFFSET(constrained_intra_pred), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, 
FLAGS },
+
     { NULL },
 };
 
diff --git a/libavcodec/d3d12va_encode_hevc.c b/libavcodec/d3d12va_encode_hevc.c
index 8cae7a8b66..d2a862ac8b 100644
--- a/libavcodec/d3d12va_encode_hevc.c
+++ b/libavcodec/d3d12va_encode_hevc.c
@@ -46,6 +46,7 @@ typedef struct D3D12VAEncodeHEVCContext {
     int qp;
     int profile;
     int level;
+    int constrained_intra_pred;
 
     // Writer structures.
     FFHWBaseEncodeH265 units;
@@ -376,6 +377,7 @@ static int 
d3d12va_encode_hevc_init_sequence_params(AVCodecContext *avctx)
                                                         
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_DISABLE_LOOP_FILTER_ACROSS_SLICES);
 
     pps->deblocking_filter_control_present_flag = 1;
+    pps->constrained_intra_pred_flag = priv->constrained_intra_pred;
 
     return 0;
 }
@@ -387,6 +389,7 @@ static int 
d3d12va_encode_hevc_get_encoder_caps(AVCodecContext *avctx)
     uint8_t min_cu_size, max_cu_size;
     FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
     D3D12VAEncodeContext     *ctx = avctx->priv_data;
+    D3D12VAEncodeHEVCContext *priv = avctx->priv_data;
     D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC *config;
     D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC hevc_caps;
 
@@ -439,6 +442,16 @@ static int 
d3d12va_encode_hevc_get_encoder_caps(AVCodecContext *avctx)
     if (hevc_caps.SupportFlags & 
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_TRANSFORM_SKIP_SUPPORT)
         config->ConfigurationFlags |= 
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_TRANSFORM_SKIPPING;
 
+    // Constrained intra prediction configuration
+    if (priv->constrained_intra_pred) {
+        if (hevc_caps.SupportFlags & 
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_CONSTRAINED_INTRAPREDICTION_SUPPORT)
 {
+            config->ConfigurationFlags |= 
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_CONSTRAINED_INTRAPREDICTION;
+        } else {
+            av_log(avctx, AV_LOG_WARNING, "Constrained intra prediction is not 
supported by the driver, disabling.\n");
+            priv->constrained_intra_pred = 0;
+        }
+    }
+
     if (hevc_caps.SupportFlags & 
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_P_FRAMES_IMPLEMENTED_AS_LOW_DELAY_B_FRAMES)
         ctx->bi_not_empty = 1;
 
@@ -780,6 +793,9 @@ static const AVOption d3d12va_encode_hevc_options[] = {
     { LEVEL("6.2", 186) },
 #undef LEVEL
 
+    { "constrained_intra_pred", "Constrained intra prediction 
(constrained_intra_pred_flag)",
+      OFFSET(constrained_intra_pred), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, 
FLAGS },
+
     { NULL },
 };
 
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to