webrtcsink: Don't require encoder element for pre-encoded streams

When webrtcsink takes as an input a stream that is already encoded, it
errors out when there is no encoder element available for the codec in
question.

This change makes it possible to stream an output from a camera that
already produces e.g. video/x-h264 without bloating the GStreamer
installation with a redundant H.264 encoder element.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2273>
This commit is contained in:
Jakub Adam 2025-05-21 23:31:25 +02:00
parent 80877c49c3
commit 1e205c842e
2 changed files with 24 additions and 6 deletions

View file

@ -464,9 +464,9 @@ impl Codec {
let encoder = Self::get_encoder_for_caps(caps, encoders);
let payloader = Self::get_payloader_for_codec(name, payloaders);
let encoding_info = if let (Some(encoder), Some(payloader)) = (encoder, payloader) {
let encoding_info = if let (encoder, Some(payloader)) = (encoder, payloader) {
Some(EncodingInfo {
encoder: Some(encoder),
encoder,
payloader,
output_filter: None,
})
@ -828,6 +828,20 @@ impl Codecs {
Self(codecs.values().cloned().collect())
}
pub fn list_encoders(&self) -> Codecs {
Codecs(
self.iter()
.filter(|codec| {
codec
.encoding_info
.as_ref()
.is_some_and(|info| info.encoder.is_some())
})
.cloned()
.collect(),
)
}
pub fn find_for_payloadable_caps(&self, caps: &gst::Caps) -> Option<Codec> {
self.iter()
.find(|codec| codec.caps.can_intersect(caps) && codec.encoding_info.is_some())
@ -938,9 +952,12 @@ impl Codecs {
.filter(|codec| codec.stream_type == gst::StreamType::AUDIO)
}
/// List all codecs that can be used for encoding the given caps and assign
/// a payload type to each of them. This is useful to initiate SDP negotiation.
pub fn list_encoders<'a>(caps: impl IntoIterator<Item = &'a gst::StructureRef>) -> Codecs {
/// List all codecs that can be used for encoding and/or payloading the given
/// caps and assign a payload type to each of them. This is useful to initiate
/// SDP negotiation.
pub fn list_encoders_and_payloaders<'a>(
caps: impl IntoIterator<Item = &'a gst::StructureRef>,
) -> Codecs {
let mut payload = 96..128;
Codecs(

View file

@ -4080,6 +4080,7 @@ impl BaseWebRTCSink {
codecs: &Codecs,
) -> Result<(), Error> {
let futs = if has_raw_caps(&discovery_info.caps) {
let codecs = codecs.list_encoders();
if codecs.is_empty() {
return Err(anyhow!(
"No codec available for encoding stream {}, \
@ -4331,7 +4332,7 @@ impl BaseWebRTCSink {
} else {
drop(state);
let settings = self.settings.lock().unwrap();
let codecs = Codecs::list_encoders(
let codecs = Codecs::list_encoders_and_payloaders(
settings.video_caps.iter().chain(settings.audio_caps.iter()),
);