PR #22619 opened by nyanmisaka
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22619
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22619.patch

This allows for real-time monitoring of the encoder's average QP in ffmpeg CLI.

example:
```
  Stream #0:0: Video: hevc (Main 10), d3d11(tv, bt709/unknown/unknown, 
progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 100 kb/s, 23.98 fps, 23.98 
tbn (default)
    Metadata:
      encoder         : Lavc62.28.100 hevc_amf

frame= 2979 fps=193 q=51.0 size=N/A time=00:02:04.20 bitrate=N/A speed=8.03x 
elapsed=0:00:15.46
```

Signed-off-by: nyanmisaka <[email protected]>


>From 964241635286931a373a0b6d15f2b3bdca2fc4e6 Mon Sep 17 00:00:00 2001
From: nyanmisaka <[email protected]>
Date: Wed, 25 Mar 2026 23:25:10 +0800
Subject: [PATCH] avcodec/amfenc: add encoder average QP stats

This allows for real-time monitoring of the encoder's average QP in ffmpeg CLI.

Signed-off-by: nyanmisaka <[email protected]>
---
 libavcodec/amfenc.c | 61 +++++++++++++++++++++++++++++++--------------
 1 file changed, 42 insertions(+), 19 deletions(-)

diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
index 50045b3ca3..37d5a1659d 100644
--- a/libavcodec/amfenc.c
+++ b/libavcodec/amfenc.c
@@ -197,6 +197,8 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket 
*pkt, AMFBuffer *buff
     AMFVariantStruct var = {0};
     int64_t          timestamp = AV_NOPTS_VALUE;
     int64_t          size = buffer->pVtbl->GetSize(buffer);
+    enum AVPictureType pict_type = 0;
+    int              average_qp = 0;
 
     if ((ret = ff_get_encode_buffer(avctx, pkt, size, 0)) < 0) {
         return ret;
@@ -204,27 +206,45 @@ static int amf_copy_buffer(AVCodecContext *avctx, 
AVPacket *pkt, AMFBuffer *buff
     memcpy(pkt->data, buffer->pVtbl->GetNative(buffer), size);
 
     switch (avctx->codec->id) {
-        case AV_CODEC_ID_H264:
-            buffer->pVtbl->GetProperty(buffer, 
AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, &var);
-            if(var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR) {
-                pkt->flags = AV_PKT_FLAG_KEY;
-            }
-            break;
-        case AV_CODEC_ID_HEVC:
-            buffer->pVtbl->GetProperty(buffer, 
AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE, &var);
-            if (var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR) 
{
-                pkt->flags = AV_PKT_FLAG_KEY;
-            }
-            break;
-        case AV_CODEC_ID_AV1:
-            buffer->pVtbl->GetProperty(buffer, 
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE, &var);
-            if (var.int64Value == AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_KEY) 
{
-                pkt->flags = AV_PKT_FLAG_KEY;
-            }
-        default:
-            break;
+    case AV_CODEC_ID_H264:
+        buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, 
&var);
+        pkt->flags |= AV_PKT_FLAG_KEY * (var.int64Value == 
AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR);
+        pict_type = var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR ? 
AV_PICTURE_TYPE_I :
+                    var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_I ? 
AV_PICTURE_TYPE_I :
+                    var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_P ? 
AV_PICTURE_TYPE_P :
+                    var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_B ? 
AV_PICTURE_TYPE_B : 0;
+
+        buffer->pVtbl->GetProperty(buffer, 
AMF_VIDEO_ENCODER_STATISTIC_AVERAGE_QP, &var);
+        average_qp = FFMAX((int)var.int64Value, 0);
+        break;
+    case AV_CODEC_ID_HEVC:
+        buffer->pVtbl->GetProperty(buffer, 
AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE, &var);
+        pkt->flags |= AV_PKT_FLAG_KEY * (var.int64Value == 
AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR);
+        pict_type = var.int64Value == 
AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR ? AV_PICTURE_TYPE_I :
+                    var.int64Value == 
AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_I ? AV_PICTURE_TYPE_I :
+                    var.int64Value == 
AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_P ? AV_PICTURE_TYPE_P : 0;
+
+        buffer->pVtbl->GetProperty(buffer, 
AMF_VIDEO_ENCODER_HEVC_STATISTIC_AVERAGE_QP, &var);
+        average_qp = FFMAX((int)var.int64Value, 0);
+        break;
+    case AV_CODEC_ID_AV1:
+        buffer->pVtbl->GetProperty(buffer, 
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE, &var);
+        pkt->flags |= AV_PKT_FLAG_KEY * (var.int64Value == 
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_KEY);
+        pict_type = var.int64Value == 
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_KEY ? AV_PICTURE_TYPE_I :
+                    var.int64Value == 
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_INTRA_ONLY ? AV_PICTURE_TYPE_I :
+                    var.int64Value == 
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_INTER ? AV_PICTURE_TYPE_P :
+                    var.int64Value == 
AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_SWITCH ? AV_PICTURE_TYPE_SI : 0;
+
+        buffer->pVtbl->GetProperty(buffer, 
AMF_VIDEO_ENCODER_AV1_STATISTIC_AVERAGE_Q_INDEX, &var);
+        average_qp = FFMAX((int)var.int64Value, 0); // av1 qindex
+        average_qp = (average_qp > 244) ? (average_qp <= 249 ? 62 : 63) : 
(average_qp + 3) >> 2; // av1 quantizer
+    default:
+        break;
     }
 
+    ff_encode_add_stats_side_data(pkt,
+        average_qp * FF_QP2LAMBDA, NULL, 0, pict_type);
+
     buffer->pVtbl->GetProperty(buffer, ctx->pts_property_name, &var);
 
     pkt->pts = var.int64Value; // original pts
@@ -446,6 +466,7 @@ static int amf_submit_frame(AVCodecContext *avctx, AVFrame  
  *frame, AMFSurface
 
     switch (avctx->codec->id) {
     case AV_CODEC_ID_H264:
+        AMF_ASSIGN_PROPERTY_BOOL(res, surface, 
AMF_VIDEO_ENCODER_STATISTICS_FEEDBACK, 1);
         AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, 
!!ctx->aud);
         switch (frame->pict_type) {
         case AV_PICTURE_TYPE_I:
@@ -466,6 +487,7 @@ static int amf_submit_frame(AVCodecContext *avctx, AVFrame  
  *frame, AMFSurface
         }
         break;
     case AV_CODEC_ID_HEVC:
+        AMF_ASSIGN_PROPERTY_BOOL(res, surface, 
AMF_VIDEO_ENCODER_HEVC_STATISTICS_FEEDBACK, 1);
         AMF_ASSIGN_PROPERTY_INT64(res, surface, 
AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud);
         switch (frame->pict_type) {
         case AV_PICTURE_TYPE_I:
@@ -482,6 +504,7 @@ static int amf_submit_frame(AVCodecContext *avctx, AVFrame  
  *frame, AMFSurface
         }
         break;
     case AV_CODEC_ID_AV1:
+        AMF_ASSIGN_PROPERTY_BOOL(res, surface, 
AMF_VIDEO_ENCODER_HEVC_STATISTICS_FEEDBACK, 1);
         if (frame->pict_type == AV_PICTURE_TYPE_I) {
             if (ctx->forced_idr) {
                 AMF_ASSIGN_PROPERTY_INT64(res, surface, 
AMF_VIDEO_ENCODER_AV1_FORCE_INSERT_SEQUENCE_HEADER, 1);
-- 
2.52.0

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

Reply via email to