tutorial: migrate to new ClockTime design

This commit is contained in:
François Laignel 2021-05-26 15:40:38 +02:00
parent 2c4c35deba
commit 88dfd97df6
2 changed files with 73 additions and 59 deletions

View file

@ -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);

View file

@ -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));