Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Dröge
rtp-rapid-sync-example
Compare Revisions
sender-clock-time-retrieval...rapid-synchronization
Commits (1)
Use NTP 64-bit RTP header extension for rapid synchronization
· 65147f5a
Sebastian Dröge
authored
Apr 30, 2022
65147f5a
Hide whitespace changes
Inline
Side-by-side
Cargo.lock
View file @
65147f5a
...
...
@@ -234,6 +234,19 @@ dependencies = [
"thiserror",
]
[[package]]
name = "gstreamer-base-sys"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a083493c3c340e71fa7c66eebda016e9fafc03eb1b4804cf9b2bad61994b078e"
dependencies = [
"glib-sys",
"gobject-sys",
"gstreamer-sys",
"libc",
"system-deps",
]
[[package]]
name = "gstreamer-net"
version = "0.18.0"
...
...
@@ -259,6 +272,33 @@ dependencies = [
"system-deps",
]
[[package]]
name = "gstreamer-rtp"
version = "0.18.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f97b6af1d900db0c35811a24a2c99d04bc0249ccbad54aed773f4337a39a9e3"
dependencies = [
"bitflags",
"glib",
"gstreamer",
"gstreamer-rtp-sys",
"libc",
"once_cell",
]
[[package]]
name = "gstreamer-rtp-sys"
version = "0.18.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2afde26d03b4146a39d07f576082f97b3775e7884ef3ccef5c4b7c0917e17469"
dependencies = [
"glib-sys",
"gstreamer-base-sys",
"gstreamer-sys",
"libc",
"system-deps",
]
[[package]]
name = "gstreamer-rtsp"
version = "0.18.0"
...
...
@@ -525,6 +565,7 @@ dependencies = [
"anyhow",
"futures",
"gstreamer",
"gstreamer-rtp",
"gstreamer-rtsp",
"gstreamer-rtsp-server",
"once_cell",
...
...
README.md
View file @
65147f5a
...
...
@@ -7,11 +7,13 @@ Please read the blog post for details.
The code below needs GStreamer from the git
`main`
branch at the time of
writing, or version 1.22 or newer.
##
Sender Clock Time Retrieval
##
Rapid synchronization via RTP header extensions
This branch contains the code that retrieves the sender clock times on the
receiver and renders them over the video frames on the receiver and also
prints them on stdout.
prints them on stdout. The times are synchronized between the sender and
receiver via an RTP header extension from the very beginning instead of
relying on RTCP.
Both timestamps on the video frames should be the same: the one rendered on
the sender at the top and the one rendered on the receiver at the bottom.
...
...
recv/src/main.rs
View file @
65147f5a
...
...
@@ -36,6 +36,17 @@ fn main() -> Result<(), Error> {
glib
::
closure!
(|
_playbin
:
&
gst
::
Pipeline
,
source
:
&
gst
::
Element
|
{
source
.set_property
(
"latency"
,
40u32
);
source
.set_property
(
"add-reference-timestamp-meta"
,
true
);
// Don't bother updating inter-stream offsets if the difference to the previous
// configuration is less than 1ms. The synchronization will have rounding errors
// in the range of the RTP clock rate, i.e. 1/90000s and 1/48000s in this case.
source
.connect_closure
(
"new-manager"
,
false
,
glib
::
closure!
(|
_rtspsrc
:
&
gst
::
Element
,
rtpbin
:
&
gst
::
Element
|
{
rtpbin
.set_property
(
"min-ts-offset"
,
gst
::
ClockTime
::
from_mseconds
(
1
));
}),
);
}),
);
...
...
send/Cargo.toml
View file @
65147f5a
...
...
@@ -9,5 +9,6 @@ anyhow = "1"
futures
=
"0.3"
once_cell
=
"1"
gst
=
{
version
=
"0.18"
,
package
=
"gstreamer"
,
features
=
["v1_20"]
}
gst-rtp
=
{
version
=
"0.18"
,
package
=
"gstreamer-rtp"
,
features
=
[
"v1_20"
]
}
gst-rtsp
=
{
version
=
"0.18"
,
package
=
"gstreamer-rtsp"
,
features
=
[
"v1_20"
]
}
gst-rtsp-server
=
{
version
=
"0.18"
,
package
=
"gstreamer-rtsp-server"
,
features
=
["v1_20"]
}
send/src/main.rs
View file @
65147f5a
...
...
@@ -5,6 +5,7 @@
use
gst
::
glib
;
use
gst
::
gst_error
;
use
gst
::
prelude
::
*
;
use
gst_rtp
::
prelude
::
*
;
use
gst_rtsp_server
::
prelude
::
*
;
use
anyhow
::{
Context
,
Error
};
...
...
@@ -139,6 +140,14 @@ mod media_factory {
// Configure this RTP stream to payload type 96.
video_pay
.set_property
(
"pt"
,
96u32
);
// Add RFC6051 64-bit NTP timestamp RTP header extension.
let
hdr_ext
=
gst_rtp
::
RTPHeaderExtension
::
create_from_uri
(
"urn:ietf:params:rtp-hdrext:ntp-64"
,
)
.context
(
"Creating NTP 64-bit RTP header extension"
)
?
;
hdr_ext
.set_id
(
1
);
video_pay
.emit_by_name
::
<
()
>
(
"add-extension"
,
&
[
&
hdr_ext
]);
bin
.add_many
(
&
[
&
video_src
,
&
video_overlay
,
&
video_enc
,
&
video_pay
])
.expect
(
"Failed to add video elements to bin"
);
...
...
@@ -174,6 +183,14 @@ mod media_factory {
// Configure this RTP stream to payload type 97.
audio_pay
.set_property
(
"pt"
,
97u32
);
// Add RFC6051 64-bit NTP timestamp RTP header extension.
let
hdr_ext
=
gst_rtp
::
RTPHeaderExtension
::
create_from_uri
(
"urn:ietf:params:rtp-hdrext:ntp-64"
,
)
.context
(
"Creating NTP 64-bit RTP header extension"
)
?
;
hdr_ext
.set_id
(
1
);
audio_pay
.emit_by_name
::
<
()
>
(
"add-extension"
,
&
[
&
hdr_ext
]);
bin
.add_many
(
&
[
&
audio_src
,
&
audio_enc
,
&
audio_pay
])
.expect
(
"Failed to add audio elements to bin"
);
...
...