diff --git a/doc/plugins.rst b/doc/plugins.rst index 571654df6..91f82d1af 100644 --- a/doc/plugins.rst +++ b/doc/plugins.rst @@ -643,11 +643,15 @@ Encodes into `Ogg Opus `_. * - Setting - Description * - **bitrate** - - Sets the data rate in bit per second. The special value "auto" lets libopus choose a rate (which is the default), and "max" uses the maximum possible data rate. + - Sets the data rate in bits per second. The special value "auto" lets libopus choose a rate (which is the default), and "max" uses the maximum possible data rate. * - **complexity** - Sets the `Opus complexity `_. * - **signal** - Sets the Opus signal type. Valid values are "auto" (the default), "voice" and "music". + * - **vbr yes|no|constrained** + - Sets the vbr mode. Setting to "yes" (default) enables variable bitrate, "no" forces constant bitrate and frame sizes, "constrained" uses constant bitrate analogous to CBR in AAC and MP3. + * - **packet_loss** + - Sets the expected packet loss percentage. This value can be increased from the default "0" for a more redundant stream at the expense of quality. * - **opustags yes|no** - Configures how metadata is interleaved into the stream. If set to yes, then metadata is inserted using ogg stream chaining, as specified in :rfc:`7845`. If set to no (the default), then ogg stream chaining is avoided and other output-dependent method is used, if available. diff --git a/src/encoder/plugins/OpusEncoderPlugin.cxx b/src/encoder/plugins/OpusEncoderPlugin.cxx index 5f3960446..d579d1e50 100644 --- a/src/encoder/plugins/OpusEncoderPlugin.cxx +++ b/src/encoder/plugins/OpusEncoderPlugin.cxx @@ -76,6 +76,9 @@ class PreparedOpusEncoder final : public PreparedEncoder { opus_int32 bitrate; int complexity; int signal; + int packet_loss; + int vbr; + int vbr_constraint; const bool chaining; public: @@ -118,6 +121,23 @@ PreparedOpusEncoder::PreparedOpusEncoder(const ConfigBlock &block) signal = OPUS_SIGNAL_MUSIC; else throw std::runtime_error("Invalid signal"); + + value = block.GetBlockValue("vbr", "yes"); + if (strcmp(value, "yes") == 0) { + vbr = 1U; + vbr_constraint = 0U; + } else if (strcmp(value, "no") == 0) { + vbr = 0U; + vbr_constraint = 0U; + } else if (strcmp(value, "constrained") == 0) { + vbr = 1U; + vbr_constraint = 1U; + } else + throw std::runtime_error("Invalid vbr"); + + packet_loss = block.GetBlockValue("packet_loss", 0U); + if (packet_loss > 100) + throw std::runtime_error("Invalid packet loss"); } PreparedEncoder * @@ -173,6 +193,9 @@ PreparedOpusEncoder::Open(AudioFormat &audio_format) opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate)); opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity)); opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal)); + opus_encoder_ctl(enc, OPUS_SET_VBR(vbr)); + opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(vbr_constraint)); + opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss)); return new OpusEncoder(audio_format, enc, chaining); }