Guillaume Desmottes 2023-04-10 13:34:46 +02:00
parent a455819871
commit 403004a85e
41 changed files with 64 additions and 64 deletions

View file

@ -112,7 +112,7 @@ specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-v
- fmp4mux: Add support for CMAF-style chunking, e.g. low-latency / LL HLS and DASH
- gtk4: Support for rendering GL textures on X11/EGL, X11/GLX, Wayland and macOS
- hlssink3: Allow generating i-frame-only playlist
- livesync: New element that alllows maintaining a contiguous live stream
- livesync: New element that allows maintaining a contiguous live stream
without gaps from a potentially unstable source.
- mp4mux: New non-fragmented MP4 muxer element
- spotifyaudiosrc: Support configurable bitrate

View file

@ -348,9 +348,9 @@ impl State {
true_peak
);
// Difference between targetted and calculated LUFS loudness as a linear scalefactor.
// Difference between targeted and calculated LUFS loudness as a linear scalefactor.
let offset = f64::powf(10., (self.target_i - global) / 20.);
// What the new peak would be after adjusting for the targetted loudness.
// What the new peak would be after adjusting for the targeted loudness.
let offset_tp = true_peak * offset;
// If the new peak would be more quiet than targeted one, take it. Otherwise only go as
@ -705,7 +705,7 @@ impl State {
self.process_fill_final_frame(imp, num_samples, FRAME_SIZE);
}
// Now repeatadly run the limiter, output the output gain, update the gains, copy further
// Now repeatedly run the limiter, output the output gain, update the gains, copy further
// data from the buf to limiter_buf until we have output everything.
//
// At this point we have to output 3s - (FRAME_SIZE - num_samples)

View file

@ -156,7 +156,7 @@ fn test_hrtfrender_explicit_spatial_objects() {
}
#[test]
// Caps negotation should fail if we have mismatch between input channels and
// Caps negotiation should fail if we have mismatch between input channels and
// of objects that we set via property. In this test case input has 6 channels
// but the number of spatial objects set is 2.
fn test_hrtfrender_caps_negotiation_fail() {

View file

@ -19,7 +19,7 @@ const AUDIO_SINK: &str = "audioconvert ! autoaudiosink";
// from the global accumulator(gasig), then reads these buffers at a fixed delay time, creating the adelL, adelM and adelR buffers,
// also, It multiplies the audio samples in the right channel by 0.5 * kdel, being kdel a line of values starting at 0.5 at increments of 0.001.
// Finally, those buffers are mixed with the accumulator, and an audio envelop is applied(aseg) to them.
// The result is similar to an audio echo in which the buffered samples are read at different delay times and also modified in frecuency(right channel),
// The result is similar to an audio echo in which the buffered samples are read at different delay times and also modified in frequency(right channel),
// this creates an space effect using just one channel audio input.
const CSD: &str = "
<CsoundSynthesizer>

View file

@ -127,9 +127,9 @@ impl CsoundFilter {
let spout = csound.get_spout().unwrap();
let in_chunks = idata.chunks_exact(spin.len());
let out_chuncks = odata.chunks_exact_mut(spout.len());
let out_chunks = odata.chunks_exact_mut(spout.len());
let mut end_score = false;
for (ichunk, ochunk) in in_chunks.zip(out_chuncks) {
for (ichunk, ochunk) in in_chunks.zip(out_chunks) {
spin.copy_from_slice(ichunk);
end_score = csound.perform_ksmps();
spout.copy_to_slice(ochunk);
@ -254,7 +254,7 @@ impl CsoundFilter {
);
// Get the required amount of bytes to be read from
// the adapter to fill an ouput buffer of size output_size
// the adapter to fill an output buffer of size output_size
let bytes_to_read = state.bytes_to_read(output_size);
let indata = state
@ -554,7 +554,7 @@ impl BaseTransformImpl for CsoundFilter {
// Flush previous state
if self.state.lock().unwrap().is_some() {
self.drain()
.map_err(|e| loggable_error!(CAT, "Error flusing previous state data {:?}", e))?;
.map_err(|e| loggable_error!(CAT, "Error flushing previous state data {:?}", e))?;
}
let in_info = gst_audio::AudioInfo::from_caps(incaps)

View file

@ -2472,7 +2472,7 @@
},
"hsvfilter": {
"author": "Julien Bardagi <julien.bardagi@gmail.com>",
"description": "Works within the HSV colorspace to apply tranformations to incoming frames",
"description": "Works within the HSV colorspace to apply transformations to incoming frames",
"hierarchy": [
"GstHsvFilter",
"GstVideoFilter",

View file

@ -486,7 +486,7 @@ impl Decrypter {
let block_size = {
let mut mutex_state = self.state.lock().unwrap();
// This will only be run after READY state,
// and will be guaranted to be initialized
// and will be guaranteed to be initialized
let state = mutex_state.as_mut().unwrap();
// Cleanup the adapter
state.adapter.clear();
@ -508,7 +508,7 @@ impl Decrypter {
let mut state = self.state.lock().unwrap();
// This will only be run after READY state,
// and will be guaranted to be initialized
// and will be guaranteed to be initialized
let state = state.as_mut().unwrap();
state.decrypt_into_adapter(self, &self.srcpad, &pulled_buffer, chunk_index)?;

View file

@ -98,7 +98,7 @@ impl State {
})?;
// This env variable is only meant to bypass nonce regeneration during
// tests to get determinisic results. It should never be used outside
// tests to get deterministic results. It should never be used outside
// of testing environments.
let nonce = if let Ok(val) = std::env::var("GST_SODIUM_ENCRYPT_NONCE") {
let bytes = hex::decode(val).expect("Failed to decode hex variable");
@ -216,7 +216,7 @@ impl Encrypter {
let mut state_mutex = self.state.lock().unwrap();
let mut buffers = BufferVec::new();
// This will only be run after READY state,
// and will be guaranted to be initialized
// and will be guaranteed to be initialized
let state = state_mutex.as_mut().unwrap();
// Now that all the full size blocks are pushed, drain the

View file

@ -1057,7 +1057,7 @@ impl TaskImpl for JitterBufferTask {
// It should also be possible to store latency and context_wait as
// fields of JitterBufferTask so as to avoid locking the settings.
// If latency can change during processing, a command based mechanism
// could be implemented. See the command implemention for ts-udpsink as
// could be implemented. See the command implementation for ts-udpsink as
// an example.
fn try_next(&mut self) -> BoxFuture<'_, Result<(), gst::FlowError>> {
async move {

View file

@ -519,7 +519,7 @@ update_buffer_level (TsRTPJitterBuffer * jbuf, gint * percent)
* Cri : The time of the clock at the receiver for packet i
* D + ni : The jitter when receiving packet i
*
* We see that the network delay is irrelevant here as we can elliminate D:
* We see that the network delay is irrelevant here as we can eliminate D:
*
* recv_diff(i) = (Cri + ni) - (Cr0 + n0))
*

View file

@ -406,7 +406,7 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
impl Queue {
/* Try transfering all the items from the pending queue to the DataQueue, then
/* Try transferring all the items from the pending queue to the DataQueue, then
* the current item. Errors out if the DataQueue was full, or the pending queue
* is already scheduled, in which case the current item should be added to the
* pending queue */

View file

@ -649,7 +649,7 @@ impl Async<UdpSocket> {
/// Sends data to the specified address.
///
/// Returns the number of bytes writen.
/// Returns the number of bytes written.
pub async fn send_to<A: Into<SocketAddr>>(&self, buf: &[u8], addr: A) -> io::Result<usize> {
let addr = addr.into();
self.write_with(|io| io.send_to(buf, addr)).await

View file

@ -215,7 +215,7 @@ impl Context {
/// Executes the provided function relatively to this [`Context`].
///
/// Usefull to initialze i/o sources and timers from outside
/// Usefull to initialize i/o sources and timers from outside
/// of a [`Context`].
///
/// # Panic
@ -511,7 +511,7 @@ mod tests {
});
// Panic: task has failed
// (enforced by `async-task`, see comment in `Future` impl for `JoinHanlde`).
// (enforced by `async-task`, see comment in `Future` impl for `JoinHandle`).
futures::executor::block_on(join_handle).unwrap_err();
}

View file

@ -394,7 +394,7 @@ impl Handle {
/// Executes the provided function relatively to this [`Scheduler`]'s [`Reactor`].
///
/// Usefull to initialze i/o sources and timers from outside
/// Usefull to initialize i/o sources and timers from outside
/// of a [`Scheduler`].
///
/// # Panic

View file

@ -373,7 +373,7 @@ pub trait TaskImpl: Send + 'static {
future::ok(()).boxed()
}
/// Handles an error occuring during the execution of the `Task` loop.
/// Handles an error occurring during the execution of the `Task` loop.
///
/// This include errors returned by [`Self::try_next`] & [`Self::handle_item`].
///
@ -410,7 +410,7 @@ pub trait TaskImpl: Send + 'static {
.boxed()
}
/// Handles an error occuring during the execution of a transition action.
/// Handles an error occurring during the execution of a transition action.
///
/// This handler also catches errors returned by subtasks spawned by the transition action.
///

View file

@ -505,7 +505,7 @@ mod imp_sink {
impl ElementSinkTest {
async fn forward_item(&self, item: Item) -> Result<gst::FlowSuccess, gst::FlowError> {
if !self.flushing.load(Ordering::SeqCst) {
gst::debug!(SINK_CAT, imp: self, "Fowarding {:?}", item);
gst::debug!(SINK_CAT, imp: self, "Forwarding {:?}", item);
let mut sender = self
.sender
.lock()
@ -522,7 +522,7 @@ mod imp_sink {
gst::debug!(
SINK_CAT,
imp: self,
"Not fowarding {:?} due to flushing",
"Not forwarding {:?} due to flushing",
item
);
Err(gst::FlowError::Flushing)

View file

@ -54,7 +54,7 @@ $ gst-launch-1.0 \
Writes a single variant HLS stream directly to a specified S3 (region, bucket,
path prefix) tuple. Takes the encoded audio and video stream as input, and uses
`hlssink3` if available, else `hlssink2`. HLS stream parameters such as
playlist length, segment duration, etc. can be tweaked by accesing the
playlist length, segment duration, etc. can be tweaked by accessing the
underlying sink using the `hlssink` property.
## awstranscriber

View file

@ -200,7 +200,7 @@ impl S3Src {
Ok(output.content_length as u64)
}
/* Returns the bytes, Some(error) if one occured, or a None error if interrupted */
/* Returns the bytes, Some(error) if one occurred, or a None error if interrupted */
fn get(self: &S3Src, offset: u64, length: u64) -> Result<Bytes, Option<gst::ErrorMessage>> {
let state = self.state.lock().unwrap();

View file

@ -14,7 +14,7 @@
//! multiple languages.
//!
//! This module contains the element implementation as well as the `TranslateSrcPad`
//! sublcass and its `TranslationPadTask`.
//! subclass and its `TranslationPadTask`.
//!
//! Web service specific code can be found in the `transcribe` and `translate` modules.

View file

@ -183,7 +183,7 @@ impl RaptorqDec {
}
// Build Source Block from received Data Packets and append
// Repair Packets that have the same initial sequnce number
// Repair Packets that have the same initial sequence number
let mut source_block = Vec::with_capacity(
(data_packets_num + repair_packets_num)
.checked_mul(state.symbol_size)
@ -301,7 +301,7 @@ impl RaptorqDec {
gst::debug!(
CAT,
imp: self,
"Succesfully recovered packet: seqnum: {}, len: {}, ts: {}",
"Successfully recovered packet: seqnum: {}, len: {}, ts: {}",
rtpbuf.seq(),
rtpbuf.payload_size(),
rtpbuf.timestamp(),
@ -337,7 +337,7 @@ impl RaptorqDec {
);
// Expand cyclic sequence numbers to u64, start from u16::MAX so we
// never overflow substraction.
// never overflow subtraction.
let seq = rtpbuf.seq();
let prev_seq = state.extended_media_seq.unwrap_or(65_535 + seq as u64);
@ -448,7 +448,7 @@ impl RaptorqDec {
);
// Expand cyclic sequence numbers to u64, start from u16::MAX so we
// never overflow substraction.
// never overflow subtraction.
let prev_seq = state.extended_repair_seq.unwrap_or(65_535 + i as u64);
let delta = gst_rtp::compare_seqnum(prev_seq as u16, i);
@ -763,7 +763,7 @@ impl ElementImpl for RaptorqDec {
let sink_fec_caps = gst::Caps::builder("application/x-rtp")
.field("raptor-scheme-id", fecscheme::FEC_SCHEME_ID.to_string())
// All fmtp paramters from SDP are string in caps, those are
// All fmtp parameters from SDP are string in caps, those are
// required parameters that cannot be expressed as string:
// .field("kmax", (string) [1, MAX_SOURCE_BLOCK_LEN])
// .field("t", (string) [1, MAX_ENCODING_SYMBOL_SIZE])

View file

@ -161,7 +161,7 @@ impl RaptorqEnc {
let sbl = state.symbols_per_block;
// Initial sequnce number in Repair Payload ID is a sequence number of
// Initial sequence number in Repair Payload ID is a sequence number of
// the first packet in the Source Block.
let seq = state.seqnums.first().cloned().unwrap();
@ -568,7 +568,7 @@ impl RaptorqEnc {
// this is the number of repair symbols placed in each repair packet,
// it SHALL be the same for all repair packets in a block. This include
// 1 byte of flow indication and 2 bytes of lenght indication as defined
// 1 byte of flow indication and 2 bytes of length indication as defined
// in RFC6881, section 8.2.4.
let symbols_per_packet = (mtu + 3 + symbol_size - 1) / symbol_size;
let symbols_per_block = symbols_per_packet * protected_packets_num;

View file

@ -215,7 +215,7 @@ impl RTPAv1Pay {
}
/// Look at the size the currently stored OBUs would require,
/// as well as their temportal IDs to decide if it is time to construct a
/// as well as their temporal IDs to decide if it is time to construct a
/// new packet, and what OBUs to include in it.
///
/// If `true` is passed for `force`, packets of any size will be accepted,

View file

@ -105,7 +105,7 @@ export default class WebRTCSession extends EventTarget {
}
/**
* The internal {@link external:RTCPeerConnection} used to manage the underlying WebRTC connnection with session
* The internal {@link external:RTCPeerConnection} used to manage the underlying WebRTC connection with session
* peer. Value may be null if session has no active WebRTC connection. You can listen to the
* {@link gstWebRTCAPI#event:RTCPeerConnectionChangedEvent} event to be informed when the connection is established
* or destroyed.

View file

@ -149,7 +149,7 @@ unsafe impl prelude::ObjectInterface for Signallable {
* @session_id: Id of the session the ice information is about
* @sdp_m_line_index: The mlineindex of the ice candidate
* @sdp_mid: Media ID of the ice candidate
* @candiate: Information about the candidate
* @candidate: Information about the candidate
*
* Notify the underlying webrtc object of an ICE candidate.
*/

View file

@ -2143,7 +2143,7 @@ impl WebRTCSink {
=> move |rtpbin: gst::Object, session_id: u32, _src: u32| {
let rtp_session = rtpbin.emit_by_name::<gst::Element>("get-session", &[&session_id]);
let element = element.expect("on-new-ssrc emited when webrtcsink has been disposed?");
let element = element.expect("on-new-ssrc emitted when webrtcsink has been disposed?");
let webrtcbin = webrtcbin.unwrap();
let mut state = element.imp().state.lock().unwrap();
if let Some(mut session) = state.sessions.get_mut(&session_id_str) {

View file

@ -782,7 +782,7 @@ impl JsonGstParse {
}
}
QueryViewMut::Position(q) => {
// For Time answer ourselfs, otherwise forward
// For Time answer ourselves, otherwise forward
if q.format() == gst::Format::Time {
let state = self.state.lock().unwrap();
q.set(state.last_position);
@ -792,7 +792,7 @@ impl JsonGstParse {
}
}
QueryViewMut::Duration(q) => {
// For Time answer ourselfs, otherwise forward
// For Time answer ourselves, otherwise forward
let state = self.state.lock().unwrap();
if q.format() == gst::Format::Time {
if let Some(pull) = state.pull.as_ref() {

View file

@ -1,6 +1,6 @@
# Tutorial on how to write GStreamer plugins in Rust
This tutorial is for the `gst-plugin-tutorial` plugin. This plugin provides 4 features. There are seperate turoials for `rgb2gray` and `sinesrc` feature for now and there will be more in future.
This tutorial is for the `gst-plugin-tutorial` plugin. This plugin provides 4 features. There are separate turoials for `rgb2gray` and `sinesrc` feature for now and there will be more in future.
1. [Part 1: `rgb2gray` - A Video Filter for converting RGB to grayscale](tutorial-1.md)
2. [Part 2: `sinesrc` - A raw audio sine wave source](tutorial-2.md)

View file

@ -163,7 +163,7 @@ impl GstObjectImpl for ProgressBin {}
// Implementation of gst::Element virtual methods
impl ElementImpl for ProgressBin {
// Set the element specific metadata. This information is what
// is visible from gst-inspect-1.0 and can also be programatically
// is visible from gst-inspect-1.0 and can also be programmatically
// retrieved from the gst::Registry after initial registration
// without having to load the plugin in memory.
fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {

View file

@ -170,7 +170,7 @@ impl GstObjectImpl for Rgb2Gray {}
// Implementation of gst::Element virtual methods
impl ElementImpl for Rgb2Gray {
// Set the element specific metadata. This information is what
// is visible from gst-inspect-1.0 and can also be programatically
// is visible from gst-inspect-1.0 and can also be programmatically
// retrieved from the gst::Registry after initial registration
// without having to load the plugin in memory.
fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {

View file

@ -326,7 +326,7 @@ impl GstObjectImpl for SineSrc {}
// Implementation of gst::Element virtual methods
impl ElementImpl for SineSrc {
// Set the element specific metadata. This information is what
// is visible from gst-inspect-1.0 and can also be programatically
// is visible from gst-inspect-1.0 and can also be programmatically
// retrieved from the gst::Registry after initial registration
// without having to load the plugin in memory.
fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {

View file

@ -70,7 +70,7 @@ If you now run the `gst-inspect-1.0` tool on the `libgstrstutorial.so`, it will
Lets start editing `src/lib.rs` to make this an actual GStreamer plugin.
Next we make use of the `gst::plugin_define!` `macro` from the `gstreamer` crate to set-up the static metadata of the plugin (and make the shared library recognizeable by GStreamer to be a valid plugin), and to define the name of our entry point function (`plugin_init`) where we will register all the elements that this plugin provides.
Next we make use of the `gst::plugin_define!` `macro` from the `gstreamer` crate to set-up the static metadata of the plugin (and make the shared library recognizable by GStreamer to be a valid plugin), and to define the name of our entry point function (`plugin_init`) where we will register all the elements that this plugin provides.
```rust
gst::plugin_define!(
@ -210,7 +210,7 @@ In addition, we also define a `register` function (the one that is already calle
## Type Class & Instance Initialization
As a next step we implement the `new` funtion and `class_init` functions. In the first version, this struct is empty for now but we will later use it to store all state of our element.
As a next step we implement the `new` function and `class_init` functions. In the first version, this struct is empty for now but we will later use it to store all state of our element.
```rust
use gst::glib;
@ -326,7 +326,7 @@ the convention with GStreamer elements.
Data flow of GStreamer elements is happening via pads, which are the input(s) and output(s) (or sinks and sources in GStreamer terminology) of an element. Via the pads, buffers containing actual media data, events or queries are transferred. An element can have any number of sink and source pads, but our new element will only have one of each.
To be able to declare what kinds of pads an element can create (they are not necessarily all static but could be created at runtime by the element or the application), it is necessary to install so-called pad templates during the class initialization (in the `class_init` funtion). These pad templates contain the name (or rather “name template”, it could be something like `src_%u` for e.g. pad templates that declare multiple possible pads), the direction of the pad (sink or source), the availability of the pad (is it always there, sometimes added/removed by the element or to be requested by the application) and all the possible media types (called caps) that the pad can consume (sink pads) or produce (src pads).
To be able to declare what kinds of pads an element can create (they are not necessarily all static but could be created at runtime by the element or the application), it is necessary to install so-called pad templates during the class initialization (in the `class_init` function). These pad templates contain the name (or rather “name template”, it could be something like `src_%u` for e.g. pad templates that declare multiple possible pads), the direction of the pad (sink or source), the availability of the pad (is it always there, sometimes added/removed by the element or to be requested by the application) and all the possible media types (called caps) that the pad can consume (sink pads) or produce (src pads).
In our case we only have always pads, one sink pad called “sink”, on which we can only accept RGB (BGRx to be exact) data with any width/height/framerate and one source pad called “src”, on which we will produce either RGB (BGRx) data or GRAY8 (8-bit grayscale) data. We do this by adding the following code to the class_init function.

View file

@ -121,7 +121,7 @@ impl ObjectSubclass for SineSrc {
// Our element here can output f32 and f64
fn class_init(klass: &mut Self::Class) {
// Set the element specific metadata. This information is what
// is visible from gst-inspect-1.0 and can also be programatically
// is visible from gst-inspect-1.0 and can also be programmatically
// retrieved from the gst::Registry after initial registration
// without having to load the plugin in memory.
klass.set_metadata(

View file

@ -385,7 +385,7 @@ impl State {
"change of rollup row count from {old_count} to {new_count}",
);
if old_count > new_count {
// push the captions ot the top of the window before we shrink the size of the
// push the captions on the top of the window before we shrink the size of the
// window
for _ in new_count..old_count {
self.cea708.service_state[idx]

View file

@ -586,7 +586,7 @@ extern "C" {
pub fn utf8_char_count(data: *const ::std::os::raw::c_char, size: usize) -> utf8_size_t;
}
extern "C" {
pub fn utf8_trimmed_length(data: *const utf8_char_t, charcters: utf8_size_t) -> utf8_size_t;
pub fn utf8_trimmed_length(data: *const utf8_char_t, characters: utf8_size_t) -> utf8_size_t;
}
extern "C" {
pub fn utf8_line_length(data: *const utf8_char_t) -> usize;

View file

@ -1032,7 +1032,7 @@ impl MccParse {
}
}
QueryViewMut::Position(q) => {
// For Time answer ourselfs, otherwise forward
// For Time answer ourselves, otherwise forward
if q.format() == gst::Format::Time {
let state = self.state.lock().unwrap();
q.set(state.last_position);
@ -1042,7 +1042,7 @@ impl MccParse {
}
}
QueryViewMut::Duration(q) => {
// For Time answer ourselfs, otherwise forward
// For Time answer ourselves, otherwise forward
let state = self.state.lock().unwrap();
if q.format() == gst::Format::Time {
if let Some(pull) = state.pull.as_ref() {

View file

@ -122,7 +122,7 @@ impl State {
["Stream with timecodes on each buffer required"]
);
// If we neeed to skip a buffer, increment the frame if it exists
// If we need to skip a buffer, increment the frame if it exists
// to avoid getting out of sync
if let Some(ref mut timecode) = self.expected_timecode {
timecode.increment_frame();

View file

@ -911,7 +911,7 @@ impl SccParse {
}
}
QueryViewMut::Position(q) => {
// For Time answer ourselfs, otherwise forward
// For Time answer ourselves, otherwise forward
if q.format() == gst::Format::Time {
let state = self.state.lock().unwrap();
q.set(state.last_position);
@ -921,7 +921,7 @@ impl SccParse {
}
}
QueryViewMut::Duration(q) => {
// For Time answer ourselfs, otherwise forward
// For Time answer ourselves, otherwise forward
let state = self.state.lock().unwrap();
if q.format() == gst::Format::Time {
if let Some(pull) = state.pull.as_ref() {

View file

@ -663,7 +663,7 @@ impl TtToCea608 {
if is_specialna(cc_data) {
// adapted from libcaption's generation code:
// specialna are treated as control charcters. Duplicated control charcters are discarded
// specialna are treated as control characters. Duplicated control characters are discarded
// So we write a resume after a specialna as a noop control command to break repetition detection
match state.mode {
Cea608Mode::RollUp2 => state.roll_up_2(self, mut_list),

View file

@ -262,7 +262,7 @@ impl ElementImpl for HsvFilter {
gst::subclass::ElementMetadata::new(
"HSV filter",
"Filter/Effect/Converter/Video",
"Works within the HSV colorspace to apply tranformations to incoming frames",
"Works within the HSV colorspace to apply transformations to incoming frames",
"Julien Bardagi <julien.bardagi@gmail.com>",
)
});

View file

@ -11,7 +11,7 @@
// Reference used for implementation: https://en.wikipedia.org/wiki/HSL_and_HSV
// Since the standard 'clamp' feature is still considered unstable, we provide
// a subsititute implementaion here so we can still build with the stable toolchain.
// a subsititute implementation here so we can still build with the stable toolchain.
// Source: https://github.com/rust-lang/rust/issues/44095#issuecomment-624879262
pub trait Clamp: Sized {
fn clamp<L, U>(self, lower: L, upper: U) -> Self

View file

@ -198,14 +198,14 @@ mod test {
let running_time = gst::ClockTime::from_seconds(2);
let mut messsage = VideoCompareMessage::default();
messsage.pad_distances.push(PadDistance {
let mut message = VideoCompareMessage::default();
message.pad_distances.push(PadDistance {
pad: gst::Pad::new(Some("sink_0"), gst::PadDirection::Sink),
distance: 42_f64,
});
messsage.running_time = Some(running_time);
message.running_time = Some(running_time);
let structure: gst::Structure = messsage.into();
let structure: gst::Structure = message.into();
let pad_distances = structure.get::<gst::Array>("pad-distances").unwrap();
let first = pad_distances