mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-01-23 17:38:20 +00:00
webrtcsink: expose signal for initial encoder configuration
+ Update README
This commit is contained in:
parent
b5443c5966
commit
983fcf2fbd
3 changed files with 107 additions and 37 deletions
20
README.md
20
README.md
|
@ -35,26 +35,30 @@ useful alternative.
|
|||
While this is not on the roadmap at the moment, nothing in the design prevents
|
||||
implementing this optimization.
|
||||
|
||||
* Congestion control: the element levarages transport-wide congestion control
|
||||
* Congestion control: the element leverages transport-wide congestion control
|
||||
feedback messages in order to adapt the bitrate of individual consumers' video
|
||||
encoders to the available bandwidth.
|
||||
|
||||
* Configuration: the level of user control over the element is at the moment quite
|
||||
narrow, as the only interface exposed is control over proposed codecs, as well
|
||||
as their order of priority, and disabling congestion control. Consult `gst-inspect=1.0`
|
||||
for more information.
|
||||
* Configuration: the level of user control over the element is slowly expanding,
|
||||
consult `gst-inspect-1.0` for more information on the available properties and
|
||||
signals.
|
||||
|
||||
More features are on the roadmap, focusing on mechanisms for mitigating packet
|
||||
loss.
|
||||
* Packet loss mitigation: webrtcsink now supports sending protection packets for
|
||||
Forward Error Correction, modulating the amount as a function of the available
|
||||
bandwidth, and can honor retransmission requests. Both features can be disabled
|
||||
via properties.
|
||||
|
||||
It is important to note that full control over the individual elements used by
|
||||
`webrtcsink` is *not* on the roadmap, as it will act as a black box in that respect,
|
||||
for example `webrtcsink` wants to reserve control over the bitrate for congestion
|
||||
control.
|
||||
|
||||
A signal is now available however for the application to provide the initial
|
||||
configuration for the encoders `webrtcsink` instantiates.
|
||||
|
||||
If more granular control is required, applications should use `webrtcbin` directly,
|
||||
`webrtcsink` will focus on trying to just do the right thing, although it might
|
||||
expose interfaces to guide and tune the heuristics it employs.
|
||||
expose more interfaces to guide and tune the heuristics it employs.
|
||||
|
||||
[example project]: https://github.com/centricular/webrtcsink-custom-signaller
|
||||
|
||||
|
|
|
@ -133,6 +133,24 @@ async fn run(args: Args) -> Result<(), Error> {
|
|||
.by_name("ws")
|
||||
.unwrap();
|
||||
|
||||
ws.connect("encoder-setup", false, |values| {
|
||||
let encoder = values[3].get::<gst::Element>().unwrap();
|
||||
|
||||
info!("Encoder: {}", encoder.factory().unwrap().name());
|
||||
|
||||
let configured = match encoder.factory().unwrap().name().as_str() {
|
||||
"does-not-exist" => {
|
||||
// One could configure a hardware encoder to their liking here,
|
||||
// and return true to make sure webrtcsink does not do any configuration
|
||||
// of its own
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
Some(configured.to_value())
|
||||
});
|
||||
|
||||
let ws_clone = ws.downgrade();
|
||||
let state_clone = state.clone();
|
||||
task::spawn(async move {
|
||||
|
|
|
@ -296,6 +296,45 @@ fn make_converter_for_video_caps(caps: &gst::Caps) -> Result<gst::Element, Error
|
|||
.upcast())
|
||||
}
|
||||
|
||||
/// Default configuration for known encoders, can be disabled
|
||||
/// by returning True from an encoder-setup handler
|
||||
fn configure_encoder(codec: &Codec, enc: &gst::Element) {
|
||||
match codec.encoder.name().as_str() {
|
||||
"vp8enc" | "vp9enc" => {
|
||||
enc.set_property("deadline", 1i64);
|
||||
enc.set_property("threads", 12i32);
|
||||
enc.set_property("target-bitrate", 2560000i32);
|
||||
enc.set_property("cpu-used", -16i32);
|
||||
enc.set_property("keyframe-max-dist", 2000i32);
|
||||
enc.set_property_from_str("keyframe-mode", "disabled");
|
||||
enc.set_property_from_str("end-usage", "cbr");
|
||||
enc.set_property("buffer-initial-size", 100i32);
|
||||
enc.set_property("buffer-optimal-size", 120i32);
|
||||
enc.set_property("buffer-size", 150i32);
|
||||
enc.set_property("resize-allowed", true);
|
||||
enc.set_property("max-intra-bitrate", 250i32);
|
||||
enc.set_property_from_str("error-resilient", "default");
|
||||
enc.set_property("lag-in-frames", 0i32);
|
||||
}
|
||||
"x264enc" => {
|
||||
enc.set_property("bitrate", 2048u32);
|
||||
enc.set_property_from_str("tune", "zerolatency");
|
||||
enc.set_property_from_str("speed-preset", "ultrafast");
|
||||
enc.set_property("threads", 12u32);
|
||||
enc.set_property("key-int-max", 2560u32);
|
||||
enc.set_property("b-adapt", false);
|
||||
enc.set_property("vbv-buf-capacity", 120u32);
|
||||
}
|
||||
"nvh264enc" => {
|
||||
enc.set_property("bitrate", 2048u32);
|
||||
enc.set_property("gop-size", 2560i32);
|
||||
enc.set_property_from_str("rc-mode", "cbr-ld-hq");
|
||||
enc.set_property("zerolatency", true);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
/// Bit of an awkward function, but the goal here is to keep
|
||||
/// most of the encoding code for consumers in line with
|
||||
/// the codec discovery code, and this gets the job done.
|
||||
|
@ -376,37 +415,8 @@ fn setup_encoding(
|
|||
|
||||
match codec.encoder.name().as_str() {
|
||||
"vp8enc" | "vp9enc" => {
|
||||
enc.set_property("deadline", 1i64);
|
||||
enc.set_property("threads", 12i32);
|
||||
enc.set_property("target-bitrate", 2560000i32);
|
||||
enc.set_property("cpu-used", -16i32);
|
||||
enc.set_property("keyframe-max-dist", 2000i32);
|
||||
enc.set_property_from_str("keyframe-mode", "disabled");
|
||||
enc.set_property_from_str("end-usage", "cbr");
|
||||
enc.set_property("buffer-initial-size", 100i32);
|
||||
enc.set_property("buffer-optimal-size", 120i32);
|
||||
enc.set_property("buffer-size", 150i32);
|
||||
enc.set_property("resize-allowed", true);
|
||||
enc.set_property("max-intra-bitrate", 250i32);
|
||||
enc.set_property_from_str("error-resilient", "default");
|
||||
enc.set_property("lag-in-frames", 0i32);
|
||||
pay.set_property_from_str("picture-id-mode", "15-bit");
|
||||
}
|
||||
"x264enc" => {
|
||||
enc.set_property("bitrate", 2048u32);
|
||||
enc.set_property_from_str("tune", "zerolatency");
|
||||
enc.set_property_from_str("speed-preset", "ultrafast");
|
||||
enc.set_property("threads", 12u32);
|
||||
enc.set_property("key-int-max", 2560u32);
|
||||
enc.set_property("b-adapt", false);
|
||||
enc.set_property("vbv-buf-capacity", 120u32);
|
||||
}
|
||||
"nvh264enc" => {
|
||||
enc.set_property("bitrate", 2048u32);
|
||||
enc.set_property("gop-size", 2560i32);
|
||||
enc.set_property_from_str("rc-mode", "cbr-ld-hq");
|
||||
enc.set_property("zerolatency", true);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
|
@ -1059,6 +1069,23 @@ impl Consumer {
|
|||
false,
|
||||
)?;
|
||||
|
||||
let encoder_was_configured: bool = element.emit_by_name(
|
||||
"encoder-setup",
|
||||
&[&self.peer_id, &webrtc_pad.stream_name, &enc],
|
||||
);
|
||||
|
||||
if !encoder_was_configured {
|
||||
gst_debug!(CAT, obj: element, "configuring encoder {:?}", enc);
|
||||
configure_encoder(codec, &enc);
|
||||
} else {
|
||||
gst_debug!(
|
||||
CAT,
|
||||
obj: element,
|
||||
"the encoder {:?} was configured through the signal handler",
|
||||
enc
|
||||
);
|
||||
}
|
||||
|
||||
// At this point, the peer has provided its answer, and we want to
|
||||
// let the payloader / encoder perform negotiation according to that.
|
||||
//
|
||||
|
@ -2551,6 +2578,27 @@ impl ObjectImpl for WebRTCSink {
|
|||
res
|
||||
})
|
||||
.build(),
|
||||
/*
|
||||
* RsWebRTCSink::encoder-setup:
|
||||
* @consumer_id: Identifier of the consumer
|
||||
* @pad_name: The name of the corresponding input pad
|
||||
* @encoder: The constructed encoder
|
||||
*
|
||||
* This signal can be used to tweak @encoder properties.
|
||||
*
|
||||
* Returns: True if the encoder is entirely configured,
|
||||
* False if webrtcsink should apply a default configuration
|
||||
*/
|
||||
glib::subclass::Signal::builder(
|
||||
"encoder-setup",
|
||||
&[
|
||||
String::static_type().into(),
|
||||
String::static_type().into(),
|
||||
gst::Element::static_type().into(),
|
||||
],
|
||||
bool::static_type().into(),
|
||||
)
|
||||
.build(),
|
||||
]
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue