From 93a54093ec821e9c46fd8cefcb3f06f54777b05e Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Tue, 4 Aug 2020 16:33:34 +0200 Subject: [PATCH] mpeg2enc: add disable-encode-retries property MJPEG Tools may reencode pictures in a second pass to stick closer to the target bitrate. This can result in slower than real-time encoding for full HD content in certain situations, as entire GOPs need reencoding when the reference picture is reencoded. See https://sourceforge.net/p/mjpeg/bugs/141/ for background Part-of: --- docs/plugins/gst_plugins_cache.json | 13 +++++++++++++ ext/mpeg2enc/gstmpeg2encoder.cc | 11 ++++++++++- ext/mpeg2enc/gstmpeg2encoder.hh | 1 + ext/mpeg2enc/gstmpeg2encoptions.cc | 29 ++++++++++++++++++++++++++++- ext/mpeg2enc/gstmpeg2encoptions.hh | 2 ++ 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/docs/plugins/gst_plugins_cache.json b/docs/plugins/gst_plugins_cache.json index 389823f..44fe4d7 100644 --- a/docs/plugins/gst_plugins_cache.json +++ b/docs/plugins/gst_plugins_cache.json @@ -207739,6 +207739,7 @@ "description": "High-quality MPEG-1/2 video encoder", "hierarchy": [ "GstMpeg2enc", + "GstVideoEncoder", "GstElement", "GstObject", "GInitiallyUnowned", @@ -207864,6 +207865,18 @@ "type": "gboolean", "writable": true }, + "disable-encode-retries": { + "blurb": "Prevent the encoder from reencoding pictures in a second pass. This can vastly improve performance, but potentially affect reaching bitrate targets.", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, "dualprime": { "blurb": "Dual Prime Motion Estimation Mode for MPEG-2 I/P-frame only streams. Quite some players do not support this.", "conditionally-available": false, diff --git a/ext/mpeg2enc/gstmpeg2encoder.cc b/ext/mpeg2enc/gstmpeg2encoder.cc index ada07ad..a44acea 100644 --- a/ext/mpeg2enc/gstmpeg2encoder.cc +++ b/ext/mpeg2enc/gstmpeg2encoder.cc @@ -40,6 +40,14 @@ #include "gstmpeg2enc.hh" #include "gstmpeg2encoder.hh" +class GstOnTheFlyPass2 : public OnTheFlyPass2 { + public: + GstOnTheFlyPass2 (EncoderParams &encoder, gboolean disable_encode_retries): OnTheFlyPass2(encoder), disable_encode_retries(disable_encode_retries) {} + bool ReencodeRequired() const { return disable_encode_retries ? false : OnTheFlyPass2::ReencodeRequired(); } + private: + gboolean disable_encode_retries; +}; + /* * Class init stuff. */ @@ -52,6 +60,7 @@ MPEG2Encoder (*options) caps = in_caps; gst_caps_ref (in_caps); init_done = FALSE; + disable_encode_retries = options->disable_encode_retries; } GstMpeg2Encoder::~GstMpeg2Encoder () @@ -89,7 +98,7 @@ gboolean GstMpeg2Encoder::setup () /* encoding internals */ quantizer = new Quantizer (parms); pass1ratectl = new OnTheFlyPass1 (parms); - pass2ratectl = new OnTheFlyPass2 (parms); + pass2ratectl = new GstOnTheFlyPass2 (parms, disable_encode_retries); /* sequencer */ seqencoder = new SeqEncoder (parms, *reader, *quantizer, *writer, *pass1ratectl, *pass2ratectl); diff --git a/ext/mpeg2enc/gstmpeg2encoder.hh b/ext/mpeg2enc/gstmpeg2encoder.hh index 5ea9ba5..02f0a3f 100644 --- a/ext/mpeg2enc/gstmpeg2encoder.hh +++ b/ext/mpeg2enc/gstmpeg2encoder.hh @@ -48,6 +48,7 @@ private: GstElement *element; GstCaps *caps; gboolean init_done; + gboolean disable_encode_retries; }; #endif /* __GST_MPEG2ENCODER_H__ */ diff --git a/ext/mpeg2enc/gstmpeg2encoptions.cc b/ext/mpeg2enc/gstmpeg2encoptions.cc index 3752ee0..b6fddc3 100644 --- a/ext/mpeg2enc/gstmpeg2encoptions.cc +++ b/ext/mpeg2enc/gstmpeg2encoptions.cc @@ -70,7 +70,8 @@ enum ARG_CORRECT_SVCD_HDS, ARG_ALTSCAN_MPEG2, ARG_CONSTRAINTS, - ARG_DUALPRIME_MPEG2 + ARG_DUALPRIME_MPEG2, + ARG_DISABLE_ENCODE_RETRIES, /* FILL ME */ }; @@ -302,6 +303,7 @@ MPEG2EncOptions () /* set some default(s) not set in base class */ bitrate = DEFAULT_BITRATE * 1000; + disable_encode_retries = FALSE; } /* @@ -501,6 +503,25 @@ GstMpeg2EncOptions::initProperties (GObjectClass * klass) "streams. Quite some players do not support this.", FALSE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + /** + * mpeg2enc:disable-encode-retries: + * + * Prevent the encoder from reencoding pictures in a second pass. + * + * This can vastly improve performance, but potentially affect reaching + * bitrate targets. + * + * See https://sourceforge.net/p/mjpeg/bugs/141/ for some background. + * + * Since: 1.18 + */ + g_object_class_install_property (klass, ARG_DISABLE_ENCODE_RETRIES, + g_param_spec_boolean ("disable-encode-retries", "Disable encode retries", + "Prevent the encoder from reencoding pictures in a second pass." + " This can vastly improve performance, but potentially affect reaching" + " bitrate targets.", + FALSE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + gst_type_mark_as_plugin_api (GST_TYPE_MPEG2ENC_ASPECT, (GstPluginAPIFlags) 0); gst_type_mark_as_plugin_api (GST_TYPE_MPEG2ENC_FORMAT, (GstPluginAPIFlags) 0); gst_type_mark_as_plugin_api (GST_TYPE_MPEG2ENC_FRAMERATE, (GstPluginAPIFlags) 0); @@ -633,6 +654,9 @@ GstMpeg2EncOptions::getProperty (guint prop_id, GValue * value) case ARG_DUALPRIME_MPEG2: g_value_set_boolean (value, hack_dualprime); break; + case ARG_DISABLE_ENCODE_RETRIES: + g_value_set_boolean (value, disable_encode_retries); + break; default: break; } @@ -769,6 +793,9 @@ GstMpeg2EncOptions::setProperty (guint prop_id, const GValue * value) case ARG_DUALPRIME_MPEG2: hack_dualprime = g_value_get_boolean (value); break; + case ARG_DISABLE_ENCODE_RETRIES: + disable_encode_retries = g_value_get_boolean (value); + break; default: break; } diff --git a/ext/mpeg2enc/gstmpeg2encoptions.hh b/ext/mpeg2enc/gstmpeg2encoptions.hh index 011c15e..d3ecd81 100644 --- a/ext/mpeg2enc/gstmpeg2encoptions.hh +++ b/ext/mpeg2enc/gstmpeg2encoptions.hh @@ -38,6 +38,8 @@ public: GValue *value); void setProperty (guint prop_id, const GValue *value); + + gboolean disable_encode_retries; }; #endif /* __GST_MPEG2ENCOPTIONS_H__ */ -- 2.7.4