webrtcsink: Support av1 via nvav1enc, av1enc, and rav1enc

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1572>
This commit is contained in:
cdelguercio 2024-05-10 11:40:13 -07:00 committed by Sebastian Dröge
parent b12da2c543
commit f5a7de9dc3
3 changed files with 67 additions and 18 deletions

View file

@ -8800,7 +8800,7 @@
"type": "GstWebRTCSinkPad"
},
"video_%%u": {
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\nvideo/x-av1:\n",
"direction": "sink",
"presence": "request",
"type": "GstWebRTCSinkPad"
@ -8833,7 +8833,7 @@
"type": "GstWebRTCSinkPad"
},
"video_%%u": {
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\nvideo/x-av1:\n",
"direction": "sink",
"presence": "request",
"type": "GstWebRTCSinkPad"
@ -8880,7 +8880,7 @@
"type": "GstWebRTCSinkPad"
},
"video_%%u": {
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\nvideo/x-av1:\n",
"direction": "sink",
"presence": "request",
"type": "GstWebRTCSinkPad"
@ -8912,7 +8912,7 @@
"type": "GstWebRTCSrcPad"
},
"video_%%u": {
"caps": "video/x-raw(ANY):\napplication/x-rtp:\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
"caps": "video/x-raw(ANY):\napplication/x-rtp:\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\nvideo/x-av1:\n",
"direction": "src",
"presence": "sometimes",
"type": "GstWebRTCSrcPad"
@ -8945,7 +8945,7 @@
"type": "GstWebRTCSinkPad"
},
"video_%%u": {
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\nvideo/x-av1:\n",
"direction": "sink",
"presence": "request",
"type": "GstWebRTCSinkPad"
@ -8979,7 +8979,7 @@
"type": "GstWebRTCSrcPad"
},
"video_%%u": {
"caps": "video/x-raw(ANY):\napplication/x-rtp:\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
"caps": "video/x-raw(ANY):\napplication/x-rtp:\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\nvideo/x-av1:\n",
"direction": "src",
"presence": "sometimes",
"type": "GstWebRTCSrcPad"
@ -9012,7 +9012,7 @@
"type": "GstWebRTCSinkPad"
},
"video_%%u": {
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
"caps": "video/x-raw:\n\nvideo/x-raw(memory:CUDAMemory):\n\nvideo/x-raw(memory:GLMemory):\n\nvideo/x-raw(memory:NVMM):\n\nvideo/x-raw(memory:D3D11Memory):\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\nvideo/x-av1:\n",
"direction": "sink",
"presence": "request",
"type": "GstWebRTCSinkPad"
@ -9044,7 +9044,7 @@
"type": "GstWebRTCSrcPad"
},
"video_%%u": {
"caps": "video/x-raw(ANY):\napplication/x-rtp:\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\n",
"caps": "video/x-raw(ANY):\napplication/x-rtp:\nvideo/x-vp8:\nvideo/x-h264:\nvideo/x-vp9:\nvideo/x-h265:\nvideo/x-av1:\n",
"direction": "src",
"presence": "sometimes",
"type": "GstWebRTCSrcPad"
@ -9260,7 +9260,7 @@
"construct": false,
"construct-only": false,
"controllable": false,
"default": "video/x-vp8; video/x-h264; video/x-vp9; video/x-h265",
"default": "video/x-vp8; video/x-h264; video/x-vp9; video/x-h265; video/x-av1",
"mutable": "ready",
"readable": true,
"type": "GstCaps",
@ -9467,7 +9467,7 @@
"writable": true
},
"video-codecs": {
"blurb": "Names of video codecs to be be used during the SDP negotiation. Valid values: [VP8, H264, VP9, H265]",
"blurb": "Names of video codecs to be be used during the SDP negotiation. Valid values: [VP8, H264, VP9, H265, AV1]",
"conditionally-available": false,
"construct": false,
"construct-only": false,

View file

@ -680,6 +680,7 @@ impl Codec {
match self.name.as_str() {
"H264" => make_element("h264parse", None),
"H265" => make_element("h265parse", None),
"AV1" => make_element("av1parse", None),
_ => return Ok(None),
}
.map(Some)
@ -723,6 +724,7 @@ pub static VP8_CAPS: Lazy<gst::Caps> = Lazy::new(|| gst::Caps::new_empty_simple(
pub static VP9_CAPS: Lazy<gst::Caps> = Lazy::new(|| gst::Caps::new_empty_simple("video/x-vp9"));
pub static H264_CAPS: Lazy<gst::Caps> = Lazy::new(|| gst::Caps::new_empty_simple("video/x-h264"));
pub static H265_CAPS: Lazy<gst::Caps> = Lazy::new(|| gst::Caps::new_empty_simple("video/x-h265"));
pub static AV1_CAPS: Lazy<gst::Caps> = Lazy::new(|| gst::Caps::new_empty_simple("video/x-av1"));
pub static RTP_CAPS: Lazy<gst::Caps> =
Lazy::new(|| gst::Caps::new_empty_simple("application/x-rtp"));
@ -814,6 +816,14 @@ static CODECS: Lazy<Codecs> = Lazy::new(|| {
&encoders,
&payloaders,
),
Codec::new(
"AV1",
gst::StreamType::VIDEO,
&AV1_CAPS,
&decoders,
&encoders,
&payloaders,
),
])
});

View file

@ -760,13 +760,31 @@ fn configure_encoder(enc: &gst::Element, start_bitrate: u32) {
enc.set_property("disable-hrd-conformance", true);
enc.set_property_from_str("rate-control", "cbr");
}
"nvav1enc" => {
enc.set_property("bitrate", start_bitrate / 1000);
enc.set_property("gop-size", -1i32);
enc.set_property_from_str("rc-mode", "cbr");
enc.set_property("zerolatency", true);
}
"av1enc" => {
enc.set_property("target-bitrate", start_bitrate / 1000);
enc.set_property_from_str("end-usage", "cbr");
enc.set_property("keyframe-max-dist", i32::MAX);
enc.set_property_from_str("usage-profile", "real-time");
}
"rav1enc" => {
enc.set_property("bitrate", start_bitrate);
enc.set_property("low-latency", true);
enc.set_property("max-key-frame-interval", 715827882);
enc.set_property("speed-preset", 10);
}
_ => (),
}
}
}
/// Default configuration for known payloaders, can be disabled
/// by returning True from an payloader-setup handler.
/// by returning True from a payloader-setup handler.
fn configure_payloader(pay: &gst::Element) {
pay.set_property("mtu", 1200_u32);
@ -964,16 +982,19 @@ impl VideoEncoder {
| "nvv4l2h264enc"
| "nvv4l2vp8enc"
| "nvv4l2vp9enc"
| "nvav1enc"
| "av1enc"
| "rav1enc"
)
}
fn bitrate(&self) -> Result<i32, WebRTCSinkError> {
let bitrate = match self.factory_name.as_str() {
"vp8enc" | "vp9enc" => self.element.property::<i32>("target-bitrate"),
"x264enc" | "nvh264enc" | "vaapih264enc" | "vaapivp8enc" | "qsvh264enc" => {
(self.element.property::<u32>("bitrate") * 1000) as i32
}
"nvv4l2h264enc" | "nvv4l2vp8enc" | "nvv4l2vp9enc" => {
"av1enc" => (self.element.property::<u32>("target-bitrate") * 1000) as i32,
"x264enc" | "nvh264enc" | "vaapih264enc" | "vaapivp8enc" | "qsvh264enc"
| "nvav1enc" => (self.element.property::<u32>("bitrate") * 1000) as i32,
"nvv4l2h264enc" | "nvv4l2vp8enc" | "nvv4l2vp9enc" | "rav1enc" => {
(self.element.property::<u32>("bitrate")) as i32
}
_ => return Err(WebRTCSinkError::BitrateNotSupported),
@ -1003,11 +1024,15 @@ impl VideoEncoder {
) -> Result<(), WebRTCSinkError> {
match self.factory_name.as_str() {
"vp8enc" | "vp9enc" => self.element.set_property("target-bitrate", bitrate),
"x264enc" | "nvh264enc" | "vaapih264enc" | "vaapivp8enc" | "qsvh264enc" => {
"av1enc" => self
.element
.set_property("target-bitrate", (bitrate / 1000) as u32),
"x264enc" | "nvh264enc" | "vaapih264enc" | "vaapivp8enc" | "qsvh264enc"
| "nvav1enc" => {
self.element
.set_property("bitrate", (bitrate / 1000) as u32);
}
"nvv4l2h264enc" | "nvv4l2vp8enc" | "nvv4l2vp9enc" => {
"nvv4l2h264enc" | "nvv4l2vp8enc" | "nvv4l2vp9enc" | "rav1enc" => {
self.element.set_property("bitrate", bitrate as u32)
}
_ => return Err(WebRTCSinkError::BitrateNotSupported),
@ -1658,7 +1683,21 @@ impl BaseWebRTCSink {
);
if let Some(ssrc) = ssrc {
payloader.set_property("ssrc", ssrc);
if let Some(pspec) = payloader.find_property("ssrc") {
match pspec.value_type() {
glib::Type::I64 => {
payloader.set_property("ssrc", ssrc as i64);
}
glib::Type::U32 => {
payloader.set_property("ssrc", ssrc);
}
_ => {
gst::warning!(CAT, imp: self, "Unsupported ssrc type (expected i64 or u32)");
}
}
} else {
gst::warning!(CAT, imp: self, "Failed to find 'ssrc' property on payloader");
}
}
if self.settings.lock().unwrap().do_clock_signalling {