mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-25 13:01:07 +00:00
tutorial: migrate to new ClockTime design
This commit is contained in:
parent
2c4c35deba
commit
88dfd97df6
2 changed files with 73 additions and 59 deletions
|
@ -432,7 +432,7 @@ impl BaseSrcImpl for SineSrc {
|
||||||
// in nanoseconds
|
// in nanoseconds
|
||||||
let old_rate = match state.info {
|
let old_rate = match state.info {
|
||||||
Some(ref info) => info.rate() as u64,
|
Some(ref info) => info.rate() as u64,
|
||||||
None => gst::SECOND_VAL,
|
None => *gst::ClockTime::SECOND,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update sample offset and accumulator based on the previous values and the
|
// Update sample offset and accumulator based on the previous values and the
|
||||||
|
@ -497,11 +497,11 @@ impl BaseSrcImpl for SineSrc {
|
||||||
let state = self.state.lock().unwrap();
|
let state = self.state.lock().unwrap();
|
||||||
|
|
||||||
if let Some(ref info) = state.info {
|
if let Some(ref info) = state.info {
|
||||||
let latency = gst::SECOND
|
let latency = gst::ClockTime::SECOND
|
||||||
.mul_div_floor(settings.samples_per_buffer as u64, info.rate() as u64)
|
.mul_div_floor(settings.samples_per_buffer as u64, info.rate() as u64)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
gst_debug!(CAT, obj: element, "Returning latency {}", latency);
|
gst_debug!(CAT, obj: element, "Returning latency {}", latency);
|
||||||
q.set(settings.is_live, latency, gst::CLOCK_TIME_NONE);
|
q.set(settings.is_live, latency, gst::ClockTime::NONE);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -556,7 +556,7 @@ impl BaseSrcImpl for SineSrc {
|
||||||
// don't know any sample rate yet. It will be converted correctly
|
// don't know any sample rate yet. It will be converted correctly
|
||||||
// once a sample rate is known.
|
// once a sample rate is known.
|
||||||
let rate = match state.info {
|
let rate = match state.info {
|
||||||
None => gst::SECOND_VAL,
|
None => *gst::ClockTime::SECOND,
|
||||||
Some(ref info) => info.rate() as u64,
|
Some(ref info) => info.rate() as u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -566,12 +566,13 @@ impl BaseSrcImpl for SineSrc {
|
||||||
let sample_offset = segment
|
let sample_offset = segment
|
||||||
.start()
|
.start()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.mul_div_floor(rate, gst::SECOND_VAL)
|
.nseconds()
|
||||||
|
.mul_div_floor(rate, *gst::ClockTime::SECOND)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let sample_stop = segment
|
let sample_stop = segment
|
||||||
.stop()
|
.stop()
|
||||||
.map(|v| v.mul_div_floor(rate, gst::SECOND_VAL).unwrap());
|
.and_then(|v| v.nseconds().mul_div_floor(rate, *gst::ClockTime::SECOND));
|
||||||
|
|
||||||
let accumulator =
|
let accumulator =
|
||||||
(sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64));
|
(sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64));
|
||||||
|
@ -606,8 +607,8 @@ impl BaseSrcImpl for SineSrc {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sample_offset = segment.start().unwrap();
|
let sample_offset = *segment.start().unwrap();
|
||||||
let sample_stop = segment.stop().0;
|
let sample_stop = segment.stop().map(|stop| *stop);
|
||||||
|
|
||||||
let accumulator =
|
let accumulator =
|
||||||
(sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64));
|
(sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64));
|
||||||
|
@ -710,13 +711,13 @@ impl PushSrcImpl for SineSrc {
|
||||||
// simply the number of samples to prevent rounding errors
|
// simply the number of samples to prevent rounding errors
|
||||||
let pts = state
|
let pts = state
|
||||||
.sample_offset
|
.sample_offset
|
||||||
.mul_div_floor(gst::SECOND_VAL, info.rate() as u64)
|
.mul_div_floor(*gst::ClockTime::SECOND, info.rate() as u64)
|
||||||
.unwrap()
|
.map(gst::ClockTime::from_nseconds)
|
||||||
.into();
|
.unwrap();
|
||||||
let next_pts: gst::ClockTime = (state.sample_offset + n_samples)
|
let next_pts = (state.sample_offset + n_samples)
|
||||||
.mul_div_floor(gst::SECOND_VAL, info.rate() as u64)
|
.mul_div_floor(*gst::ClockTime::SECOND, info.rate() as u64)
|
||||||
.unwrap()
|
.map(gst::ClockTime::from_nseconds)
|
||||||
.into();
|
.unwrap();
|
||||||
buffer.set_pts(pts);
|
buffer.set_pts(pts);
|
||||||
buffer.set_duration(next_pts - pts);
|
buffer.set_duration(next_pts - pts);
|
||||||
|
|
||||||
|
@ -764,14 +765,22 @@ impl PushSrcImpl for SineSrc {
|
||||||
|
|
||||||
let segment = element.segment().downcast::<gst::format::Time>().unwrap();
|
let segment = element.segment().downcast::<gst::format::Time>().unwrap();
|
||||||
let base_time = element.base_time();
|
let base_time = element.base_time();
|
||||||
let running_time = segment.to_running_time(buffer.pts() + buffer.duration());
|
let running_time = segment.to_running_time(
|
||||||
|
buffer
|
||||||
|
.pts()
|
||||||
|
.zip(buffer.duration())
|
||||||
|
.map(|(pts, duration)| pts + duration),
|
||||||
|
);
|
||||||
|
|
||||||
// The last sample's clock time is the base time of the element plus the
|
// The last sample's clock time is the base time of the element plus the
|
||||||
// running time of the last sample
|
// running time of the last sample
|
||||||
let wait_until = running_time + base_time;
|
let wait_until = match running_time
|
||||||
if wait_until.is_none() {
|
.zip(base_time)
|
||||||
return Ok(buffer);
|
.map(|(running_time, base_time)| running_time + base_time)
|
||||||
}
|
{
|
||||||
|
Some(wait_until) => wait_until,
|
||||||
|
None => return Ok(buffer),
|
||||||
|
};
|
||||||
|
|
||||||
// Store the clock ID in our struct unless we're flushing anyway.
|
// Store the clock ID in our struct unless we're flushing anyway.
|
||||||
// This allows to asynchronously cancel the waiting from unlock()
|
// This allows to asynchronously cancel the waiting from unlock()
|
||||||
|
@ -791,7 +800,7 @@ impl PushSrcImpl for SineSrc {
|
||||||
obj: element,
|
obj: element,
|
||||||
"Waiting until {}, now {}",
|
"Waiting until {}, now {}",
|
||||||
wait_until,
|
wait_until,
|
||||||
clock.time()
|
clock.time().display(),
|
||||||
);
|
);
|
||||||
let (res, jitter) = id.wait();
|
let (res, jitter) = id.wait();
|
||||||
gst_log!(CAT, obj: element, "Waited res {:?} jitter {}", res, jitter);
|
gst_log!(CAT, obj: element, "Waited res {:?} jitter {}", res, jitter);
|
||||||
|
|
|
@ -31,15 +31,23 @@ use gst_base::subclass::prelude::*;
|
||||||
|
|
||||||
use byte_slice_cast::*;
|
use byte_slice_cast::*;
|
||||||
|
|
||||||
use std::{i32, u32};
|
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::ops::Rem;
|
use std::ops::Rem;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use std::{i32, u32};
|
||||||
|
|
||||||
use num_traits::float::Float;
|
|
||||||
use num_traits::cast::NumCast;
|
use num_traits::cast::NumCast;
|
||||||
|
use num_traits::float::Float;
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
|
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
||||||
|
gst::DebugCategory::new(
|
||||||
|
"rssinesrc",
|
||||||
|
gst::DebugColorFlags::empty(),
|
||||||
|
Some("Rust Sine Wave Source"),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
// Default values of properties
|
// Default values of properties
|
||||||
const DEFAULT_SAMPLES_PER_BUFFER: u32 = 1024;
|
const DEFAULT_SAMPLES_PER_BUFFER: u32 = 1024;
|
||||||
const DEFAULT_FREQ: u32 = 440;
|
const DEFAULT_FREQ: u32 = 440;
|
||||||
|
@ -96,14 +104,6 @@ pub struct SineSrc {
|
||||||
state: Mutex<State>,
|
state: Mutex<State>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
|
||||||
gst::DebugCategory::new(
|
|
||||||
"rssinesrc",
|
|
||||||
gst::DebugColorFlags::empty(),
|
|
||||||
Some("Rust Sine Wave Source"),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
impl ObjectSubclass for SineSrc {
|
impl ObjectSubclass for SineSrc {
|
||||||
const NAME: &'static str = "RsSineSrc";
|
const NAME: &'static str = "RsSineSrc";
|
||||||
|
@ -435,7 +435,7 @@ First of all, we need to get notified whenever the caps that our source is confi
|
||||||
// in nanoseconds
|
// in nanoseconds
|
||||||
let old_rate = match state.info {
|
let old_rate = match state.info {
|
||||||
Some(ref info) => info.rate() as u64,
|
Some(ref info) => info.rate() as u64,
|
||||||
None => gst::SECOND_VAL,
|
None => gst::ClockTime::SECOND,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update sample offset and accumulator based on the previous values and the
|
// Update sample offset and accumulator based on the previous values and the
|
||||||
|
@ -611,13 +611,13 @@ Now that this is done, we need to implement the `PushSrc::create` virtual meth
|
||||||
// simply the number of samples to prevent rounding errors
|
// simply the number of samples to prevent rounding errors
|
||||||
let pts = state
|
let pts = state
|
||||||
.sample_offset
|
.sample_offset
|
||||||
.mul_div_floor(gst::SECOND_VAL, info.rate() as u64)
|
.mul_div_floor(gst::ClockTime::SECOND, info.rate() as u64)
|
||||||
.unwrap()
|
.map(gst::ClockTime::from_nseconds)
|
||||||
.into();
|
.unwrap();
|
||||||
let next_pts: gst::ClockTime = (state.sample_offset + n_samples)
|
let next_pts = (state.sample_offset + n_samples)
|
||||||
.mul_div_floor(gst::SECOND_VAL, info.rate() as u64)
|
.mul_div_floor(*gst::ClockTime::SECOND, info.rate() as u64)
|
||||||
.unwrap()
|
.map(gst::ClockTime::from_nseconds)
|
||||||
.into();
|
.unwrap();
|
||||||
buffer.set_pts(pts);
|
buffer.set_pts(pts);
|
||||||
buffer.set_duration(next_pts - pts);
|
buffer.set_duration(next_pts - pts);
|
||||||
|
|
||||||
|
@ -698,19 +698,24 @@ For working in live mode, we have to add a few different parts in various places
|
||||||
Some(clock) => clock,
|
Some(clock) => clock,
|
||||||
};
|
};
|
||||||
|
|
||||||
let segment = element
|
let segment = element.segment().downcast::<gst::format::Time>().unwrap();
|
||||||
.get_segment()
|
let base_time = element.base_time();
|
||||||
.downcast::<gst::format::Time>()
|
let running_time = segment.to_running_time(
|
||||||
.unwrap();
|
buffer
|
||||||
let base_time = element.get_base_time();
|
.pts()
|
||||||
let running_time = segment.to_running_time(buffer.get_pts() + buffer.get_duration());
|
.zip(buffer.duration())
|
||||||
|
.map(|(pts, duration)| pts + duration),
|
||||||
|
);
|
||||||
|
|
||||||
// The last sample's clock time is the base time of the element plus the
|
// The last sample's clock time is the base time of the element plus the
|
||||||
// running time of the last sample
|
// running time of the last sample
|
||||||
let wait_until = running_time + base_time;
|
let wait_until = match running_time
|
||||||
if wait_until.is_none() {
|
.zip(base_time)
|
||||||
return Ok(buffer);
|
.map(|(running_time, base_time)| running_time + base_time)
|
||||||
}
|
{
|
||||||
|
Some(wait_until) => wait_until,
|
||||||
|
None => return Ok(buffer),
|
||||||
|
};
|
||||||
|
|
||||||
let id = clock.new_single_shot_id(wait_until);
|
let id = clock.new_single_shot_id(wait_until);
|
||||||
|
|
||||||
|
@ -719,7 +724,7 @@ For working in live mode, we have to add a few different parts in various places
|
||||||
obj: element,
|
obj: element,
|
||||||
"Waiting until {}, now {}",
|
"Waiting until {}, now {}",
|
||||||
wait_until,
|
wait_until,
|
||||||
clock.get_time()
|
clock.get_time().display(),
|
||||||
);
|
);
|
||||||
let (res, jitter) = id.wait();
|
let (res, jitter) = id.wait();
|
||||||
gst_log!(
|
gst_log!(
|
||||||
|
@ -782,11 +787,11 @@ This querying is done with the `LATENCY` query, which we will have to handle i
|
||||||
let state = self.state.lock().unwrap();
|
let state = self.state.lock().unwrap();
|
||||||
|
|
||||||
if let Some(ref info) = state.info {
|
if let Some(ref info) = state.info {
|
||||||
let latency = gst::SECOND
|
let latency = gst::ClockTime::SECOND
|
||||||
.mul_div_floor(settings.samples_per_buffer as u64, info.rate() as u64)
|
.mul_div_floor(settings.samples_per_buffer as u64, info.rate() as u64)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
gst_debug!(CAT, obj: element, "Returning latency {}", latency);
|
gst_debug!(CAT, obj: element, "Returning latency {}", latency);
|
||||||
q.set(settings.is_live, latency, gst::CLOCK_TIME_NONE);
|
q.set(settings.is_live, latency, gst::ClockTime::NONE);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -889,7 +894,7 @@ Now as a last step, we need to actually make use of the new struct we added arou
|
||||||
obj: element,
|
obj: element,
|
||||||
"Waiting until {}, now {}",
|
"Waiting until {}, now {}",
|
||||||
wait_until,
|
wait_until,
|
||||||
clock.get_time()
|
clock.get_time().display(),
|
||||||
);
|
);
|
||||||
let (res, jitter) = id.wait();
|
let (res, jitter) = id.wait();
|
||||||
gst_log!(
|
gst_log!(
|
||||||
|
@ -944,7 +949,7 @@ Seeking is implemented in the `BaseSrc::do_seek` virtual method, and signallin
|
||||||
// don't know any sample rate yet. It will be converted correctly
|
// don't know any sample rate yet. It will be converted correctly
|
||||||
// once a sample rate is known.
|
// once a sample rate is known.
|
||||||
let rate = match state.info {
|
let rate = match state.info {
|
||||||
None => gst::SECOND_VAL,
|
None => *gst::ClockTime::SECOND,
|
||||||
Some(ref info) => info.rate() as u64,
|
Some(ref info) => info.rate() as u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -954,12 +959,12 @@ Seeking is implemented in the `BaseSrc::do_seek` virtual method, and signallin
|
||||||
let sample_offset = segment
|
let sample_offset = segment
|
||||||
.get_start()
|
.get_start()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.mul_div_floor(rate, gst::SECOND_VAL)
|
.mul_div_floor(rate, *gst::ClockTime::SECOND)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let sample_stop = segment
|
let sample_stop = segment
|
||||||
.get_stop()
|
.get_stop()
|
||||||
.map(|v| v.mul_div_floor(rate, gst::SECOND_VAL).unwrap());
|
.map(|v| v.mul_div_floor(rate, *gst::ClockTime::SECOND).unwrap());
|
||||||
|
|
||||||
let accumulator =
|
let accumulator =
|
||||||
(sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64));
|
(sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64));
|
||||||
|
@ -994,8 +999,8 @@ Seeking is implemented in the `BaseSrc::do_seek` virtual method, and signallin
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sample_offset = segment.get_start().unwrap();
|
let sample_offset = *segment.start().unwrap();
|
||||||
let sample_stop = segment.get_stop().0;
|
let sample_stop = segment.stop().map(|stop| *stop);
|
||||||
|
|
||||||
let accumulator =
|
let accumulator =
|
||||||
(sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64));
|
(sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64));
|
||||||
|
|
Loading…
Reference in a new issue