]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
transcoding: Add video bitrate limiter for h.264/VP8/MPEG2
authorJoakim Gissberg <joakim@gissberg.nu>
Mon, 27 Oct 2014 22:01:58 +0000 (23:01 +0100)
committerJaroslav Kysela <perex@perex.cz>
Tue, 13 Jan 2015 17:51:33 +0000 (18:51 +0100)
src/plumbing/transcoding.c
src/plumbing/transcoding.h
src/profile.c

index ed6f4e2ee412d160127ed6918b491c66db46dbeb..271d16aaeae0bc4f5cd0b4b7c72ec307fcffadc8 100644 (file)
@@ -1037,8 +1037,15 @@ transcoder_stream_video(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt)
       octx->qmin           = 1;
       octx->qmax           = FF_LAMBDA_MAX;
 
-      octx->bit_rate       = 2 * octx->width * octx->height;
-      octx->rc_max_rate    = 4 * octx->bit_rate;
+      if (t->t_props.tp_vbitrate == 0) {
+        octx->bit_rate       = 2 * octx->width * octx->height;
+        octx->rc_max_rate    = 4 * octx->bit_rate;
+
+      } else {
+        octx->bit_rate       = t->t_props.tp_vbitrate * 1000;
+        octx->rc_max_rate    = octx->bit_rate * 1.05;
+      }
+
       octx->rc_buffer_size = 2 * octx->rc_max_rate;
       break;
  
@@ -1046,14 +1053,17 @@ transcoder_stream_video(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt)
       octx->codec_id       = AV_CODEC_ID_VP8;
       octx->pix_fmt        = PIX_FMT_YUV420P;
 
-      octx->qmin = 10;
-      octx->qmax = 20;
-
       av_dict_set(&opts, "quality",  "realtime", 0);
 
-      octx->bit_rate       = 3 * octx->width * octx->height;
+      if (t->t_props.tp_vbitrate == 0) {
+        octx->qmin = 10;
+        octx->qmax = 20;
+      } else {
+        octx->bit_rate       = t->t_props.tp_vbitrate * 1000;
+        octx->rc_max_rate    = octx->bit_rate * 1.05;
+      }
+
       octx->rc_buffer_size = 8 * 1024 * 224;
-      octx->rc_max_rate    = 2 * octx->bit_rate;
       break;
 
     case SCT_H264:
@@ -1072,18 +1082,25 @@ transcoder_stream_video(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt)
 
       // Minimum quantizer. Doesn't need to be changed.
       // Recommended default: -qmin 10
-      octx->qmin = 10;
+      // octx->qmin = 10;
 
       // Maximum quantizer. Doesn't need to be changed.
       // Recommended default: -qmax 51
-      octx->qmax = 30;
+      // octx->qmax = 30;
 
       av_dict_set(&opts, "preset",  "medium", 0);
       av_dict_set(&opts, "profile", "baseline", 0);
+      av_dict_set(&opts, "tune",    "zerolatency", 0);
+
+      if (t->t_props.tp_vbitrate == 0) {
+        octx->qmin = 10;
+        octx->qmax = 30;
+      } else {
+        octx->bit_rate       = t->t_props.tp_vbitrate * 1000;
+        octx->rc_max_rate    = octx->bit_rate * 1.05;
+      }
 
-      octx->bit_rate       = 2 * octx->width * octx->height;
       octx->rc_buffer_size = 8 * 1024 * 224;
-      octx->rc_max_rate    = 2 * octx->rc_buffer_size;
       break;
 
     default:
@@ -1749,6 +1766,7 @@ transcoder_set_properties(streaming_target_t *st,
   strncpy(tp->tp_scodec, props->tp_scodec, sizeof(tp->tp_scodec)-1);
   tp->tp_channels   = props->tp_channels;
   tp->tp_bandwidth  = props->tp_bandwidth;
+  tp->tp_vbitrate   = props->tp_vbitrate;
   tp->tp_resolution = props->tp_resolution;
 
   memcpy(tp->tp_language, props->tp_language, 4);
index bbd028fa5ecb62fbde960f9aad7ceadce4d4b961..81c04e8de55855fa3b0b126530f59ebe15b6c8af 100644 (file)
@@ -27,6 +27,7 @@ typedef struct transcoder_prop {
 
   int8_t   tp_channels;
   int32_t  tp_bandwidth;
+  int32_t  tp_vbitrate;
   char     tp_language[4];
   int32_t  tp_resolution;
 
index 4795b244ecbfc9e2cdd022eb18f86029a237348c..52ed730b94f56020cb156ff86ee23ce60c51433f 100644 (file)
@@ -1019,6 +1019,7 @@ typedef struct profile_transcode {
   uint32_t pro_resolution;
   uint32_t pro_channels;
   uint32_t pro_bandwidth;
+  uint32_t pro_vbitrate;
   char    *pro_language;
   char    *pro_vcodec;
   char    *pro_acodec;
@@ -1214,6 +1215,13 @@ const idclass_t profile_transcode_class =
       .def.s    = "libx264",
       .list     = profile_class_vcodec_list,
     },
+    {
+      .type     = PT_U32,
+      .id       = "vbitrate",
+      .name     = "Video Bitrate (kb/s) (0=Auto)",
+      .off      = offsetof(profile_transcode_t, pro_vbitrate),
+      .def.u32  = 0,
+    },
     {
       .type     = PT_STR,
       .id       = "acodec",
@@ -1246,6 +1254,12 @@ profile_transcode_bandwidth(profile_transcode_t *pro)
   return pro->pro_bandwidth >= 64 ? pro->pro_bandwidth : 64;
 }
 
+static int
+profile_transcode_vbitrate(profile_transcode_t *pro)
+{
+  return pro->pro_vbitrate;
+}
+
 static int
 profile_transcode_can_share(profile_chain_t *prch,
                             profile_chain_t *joiner)
@@ -1270,6 +1284,8 @@ profile_transcode_can_share(profile_chain_t *prch,
     return 0;
   if (profile_transcode_bandwidth(pro1) != profile_transcode_bandwidth(pro2))
     return 0;
+  if (profile_transcode_vbitrate(pro1) != profile_transcode_vbitrate(pro2))
+    return 0;
   if (strcmp(pro1->pro_language ?: "", pro2->pro_language ?: ""))
     return 0;
   return 1;
@@ -1297,6 +1313,7 @@ profile_transcode_work(profile_chain_t *prch,
   props.tp_resolution = profile_transcode_resolution(pro);
   props.tp_channels   = pro->pro_channels;
   props.tp_bandwidth  = profile_transcode_bandwidth(pro);
+  props.tp_vbitrate   = profile_transcode_vbitrate(pro);
   strncpy(props.tp_language, pro->pro_language ?: "", 3);
 
   dst = prch->prch_gh = globalheaders_create(dst);
@@ -1506,6 +1523,7 @@ profile_init(void)
     htsmsg_add_u32 (conf, "resolution", 384);
     htsmsg_add_u32 (conf, "channels", 2);
     htsmsg_add_str (conf, "vcodec", "libvpx");
+    htsmsg_add_str (conf, "vbitrate", 0);
     htsmsg_add_str (conf, "acodec", "libvorbis");
     htsmsg_add_bool(conf, "shield", 1);
     (void)profile_create(NULL, conf, 1);
@@ -1525,6 +1543,7 @@ profile_init(void)
     htsmsg_add_u32 (conf, "resolution", 384);
     htsmsg_add_u32 (conf, "channels", 2);
     htsmsg_add_str (conf, "vcodec", "libx264");
+    htsmsg_add_str (conf, "vbitrate", 0);
     htsmsg_add_str (conf, "acodec", "aac");
     htsmsg_add_bool(conf, "shield", 1);
     (void)profile_create(NULL, conf, 1);
@@ -1544,6 +1563,7 @@ profile_init(void)
     htsmsg_add_u32 (conf, "resolution", 384);
     htsmsg_add_u32 (conf, "channels", 2);
     htsmsg_add_str (conf, "vcodec", "libx264");
+    htsmsg_add_str (conf, "vbitrate", 0);
     htsmsg_add_str (conf, "acodec", "aac");
     htsmsg_add_bool(conf, "shield", 1);
     (void)profile_create(NULL, conf, 1);