]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Update for VAAPI transcoding
authorOvaron <ovaron@myovaron.de>
Mon, 21 Mar 2022 18:47:08 +0000 (19:47 +0100)
committerFlole998 <Flole998@users.noreply.github.com>
Wed, 30 Mar 2022 00:55:50 +0000 (02:55 +0200)
VAAPI: Buffer factor (buffersize manipulation) now configurable at WebUI.
VAAPI: Added rc_mode (h264/hevc) and tier (hevc), both configurable via WebUI.
VAAPI: Removed B-Frame workaround from the past at HEVC.
VAAPI: Added an option for ignore b-frames because some drivers needs this (AMD).
VAAPI: Also updated VP8 and VP9 encoding.
VAAPI: VP8 and VP9 now also reacts on options for "Buffer factor" and "Ignore B-Frames" and got the "force_key_frames" expression to increase picture quality.
VAAPI: Added destroy option for h264 codec (might have created memory issues)

src/transcoding/codec/codecs/libs/vaapi.c

index 6c18d596c17435eff4d4c6f8af77bfc9e69ed972..cbcfe9b4797720b0d4193ceab126ce5909a396e3 100644 (file)
@@ -33,6 +33,10 @@ typedef struct {
     TVHVideoCodecProfile;
     int qp;
     int quality;
+    double buff_factor;
+    int rc_mode;
+    int tier;
+    int ignore_bframe;
 } tvh_codec_profile_vaapi_t;
 
 #if defined(__linux__)
@@ -142,6 +146,27 @@ static const codec_profile_class_t codec_profile_vaapi_class = {
                 .off      = offsetof(TVHCodecProfile, bit_rate),
                 .def.d    = 0,
             },
+            {
+                .type     = PT_DBL,
+                .id       = "buff_factor",
+                .name     = N_("Buffer factor"),
+                .desc     = N_("Size of transcoding buffer (buffer=bitrate*1000*factor). Good factor is 3."),
+                .group    = 3,
+                .get_opts = codec_profile_class_get_opts,
+                .off      = offsetof(tvh_codec_profile_vaapi_t, buff_factor),
+                .def.d    = 3,
+            },
+            {
+                .type     = PT_INT,
+                .id       = "rc_mode",
+                .name     = N_("Rate control mode"),
+                .desc     = N_("Set rate control mode (from 0 to 6).[0=auto 1=CQP 2=CBR 3=VBR 4=ICQ 5=QVBR 6=AVBR]"),
+                .group    = 3,
+                .get_opts = codec_profile_class_get_opts,
+                .off      = offsetof(tvh_codec_profile_vaapi_t, rc_mode),
+                .intextra = INTEXTRA_RANGE(0, 6, 0),
+                .def.d    = 0,
+            },
             {
                 .type     = PT_INT,
                 .id       = "qp",
@@ -153,6 +178,17 @@ static const codec_profile_class_t codec_profile_vaapi_class = {
                 .intextra = INTEXTRA_RANGE(0, 52, 1),
                 .def.i    = 0,
             },
+            {
+                .type     = PT_INT,
+                .id       = "ignore_bframe",
+                .name     = N_("Ignore B-Frames"),
+                .group    = 3,
+                .desc     = N_("Some VAAPI drivers cannot handle b-frames (like AMD). [0=use b-frames (default) 1=ignore b-frames]"),
+                .get_opts = codec_profile_class_get_opts,
+                .off      = offsetof(tvh_codec_profile_vaapi_t, ignore_bframe),
+                .intextra = INTEXTRA_RANGE(0, 1, 0),
+                .def.i    = 0,
+            },
             {}
         }
     },
@@ -175,10 +211,17 @@ tvh_codec_profile_vaapi_h264_open(tvh_codec_profile_vaapi_t *self,
 {
     // bit_rate or qp
     if (self->bit_rate) {
+        if (self->buff_factor <= 0) {
+            self->buff_factor = 3;
+        }
         AV_DICT_SET_BIT_RATE(opts, self->bit_rate);
         AV_DICT_SET_INT(opts, "maxrate", (self->bit_rate) * 1000, AV_DICT_DONT_OVERWRITE);
-        AV_DICT_SET_INT(opts, "bufsize", ((self->bit_rate) * 1000) * 3, AV_DICT_DONT_OVERWRITE);
+        AV_DICT_SET_INT(opts, "bufsize", ((self->bit_rate) * 1000) * self->buff_factor, AV_DICT_DONT_OVERWRITE);
         AV_DICT_SET(opts, "force_key_frames", "expr:gte(t,n_forced*3)", AV_DICT_DONT_OVERWRITE);
+        AV_DICT_SET_INT(opts, "rc_mode", self->rc_mode, AV_DICT_DONT_OVERWRITE);
+        if (self->ignore_bframe) {
+            AV_DICT_SET_INT(opts, "bf", 0, 0);
+        }
     }
     else {
         AV_DICT_SET_QP(opts, self->qp, 20);
@@ -219,6 +262,8 @@ TVHVideoCodec tvh_codec_vaapi_h264 = {
     .size     = sizeof(tvh_codec_profile_vaapi_t),
     .idclass  = &codec_profile_vaapi_h264_class,
     .profiles = vaapi_h264_profiles,
+    .profile_init = tvh_codec_profile_video_init,
+    .profile_destroy = tvh_codec_profile_video_destroy,
 };
 
 
@@ -238,17 +283,21 @@ tvh_codec_profile_vaapi_hevc_open(tvh_codec_profile_vaapi_t *self,
     // bit_rate or qp
     if (self->bit_rate) {
         AV_DICT_SET_BIT_RATE(opts, self->bit_rate);
+        if (self->buff_factor <= 0) {
+            self->buff_factor = 3;
+        }
         AV_DICT_SET_INT(opts, "maxrate", (self->bit_rate) * 1000, AV_DICT_DONT_OVERWRITE);
-        AV_DICT_SET_INT(opts, "bufsize", ((self->bit_rate) * 1000) * 3, AV_DICT_DONT_OVERWRITE);
+        AV_DICT_SET_INT(opts, "bufsize", ((self->bit_rate) * 1000) * self->buff_factor, AV_DICT_DONT_OVERWRITE);
         AV_DICT_SET(opts, "force_key_frames", "expr:gte(t,n_forced*3)", AV_DICT_DONT_OVERWRITE);
+        AV_DICT_SET_INT(opts, "rc_mode", self->rc_mode, AV_DICT_DONT_OVERWRITE);
+        AV_DICT_SET_INT(opts, "tier", self->tier, AV_DICT_DONT_OVERWRITE);
+        if (self->ignore_bframe) {
+            AV_DICT_SET_INT(opts, "bf", 0, 0);
+        }
     }
     else {
         AV_DICT_SET_QP(opts, self->qp, 25);
     }
-    // max_b_frames
-    // XXX: remove when b-frames handling in vaapi_encode is fixed
-    AV_DICT_SET_INT(opts, "bf", 0, 0);
-
     return 0;
 }
 
@@ -257,7 +306,22 @@ static const codec_profile_class_t codec_profile_vaapi_hevc_class = {
     {
         .ic_super      = (idclass_t *)&codec_profile_vaapi_class,
         .ic_class      = "codec_profile_vaapi_hevc",
-        .ic_caption    = N_("vaapi_hevc")
+        .ic_caption    = N_("vaapi_hevc"),
+        .ic_properties = (const property_t[]){
+            {
+                .type     = PT_INT,
+                .id       = "tier",
+                .name     = N_("Tier"),
+                .desc     = N_("Set tier (general_tier_flag) [0=main 1=high]"),
+                .group    = 5,
+                .opts     = PO_EXPERT,
+                .get_opts = codec_profile_class_get_opts,
+                .off      = offsetof(tvh_codec_profile_vaapi_t, tier),
+                .intextra = INTEXTRA_RANGE(0, 1, 0),
+                .def.i    = 0,
+            },
+            {}
+        }
     },
     .open = (codec_profile_open_meth)tvh_codec_profile_vaapi_hevc_open,
 };
@@ -286,12 +350,19 @@ tvh_codec_profile_vaapi_vp8_open(tvh_codec_profile_vaapi_t *self,
     // bit_rate or qp
     if (self->bit_rate) {
         AV_DICT_SET_BIT_RATE(opts, self->bit_rate);
+        if (self->buff_factor <= 0) {
+            self->buff_factor = 3;
+        }
+        AV_DICT_SET_INT(opts, "maxrate", (self->bit_rate) * 1000, AV_DICT_DONT_OVERWRITE);
+        AV_DICT_SET_INT(opts, "bufsize", ((self->bit_rate) * 1000) * self->buff_factor, AV_DICT_DONT_OVERWRITE);
+        AV_DICT_SET(opts, "force_key_frames", "expr:gte(t,n_forced*3)", AV_DICT_DONT_OVERWRITE);
     }
     else {
         AV_DICT_SET_QP(opts, self->qp, 25);
     }
-    // force zero here, until encoder is fixed
-    AV_DICT_SET_INT(opts, "bf", 0, 0);
+    if (self->ignore_bframe) {
+        AV_DICT_SET_INT(opts, "bf", 0, 0);
+    }
     return 0;
 }
 
@@ -328,12 +399,19 @@ tvh_codec_profile_vaapi_vp9_open(tvh_codec_profile_vaapi_t *self,
     // bit_rate or qp
     if (self->bit_rate) {
         AV_DICT_SET_BIT_RATE(opts, self->bit_rate);
+        if (self->buff_factor <= 0) {
+            self->buff_factor = 3;
+        }
+        AV_DICT_SET_INT(opts, "maxrate", (self->bit_rate) * 1000, AV_DICT_DONT_OVERWRITE);
+        AV_DICT_SET_INT(opts, "bufsize", ((self->bit_rate) * 1000) * self->buff_factor, AV_DICT_DONT_OVERWRITE);
+        AV_DICT_SET(opts, "force_key_frames", "expr:gte(t,n_forced*3)", AV_DICT_DONT_OVERWRITE);
     }
     else {
         AV_DICT_SET_QP(opts, self->qp, 25);
     }
-    // force zero here, until encoder is fixed
-    AV_DICT_SET_INT(opts, "bf", 0, 0);
+    if (self->ignore_bframe) {
+        AV_DICT_SET_INT(opts, "bf", 0, 0);
+    }
     return 0;
 }