Change *Impl trait methods to only take &self and not Self::Type in addition

This commit is contained in:
Sebastian Dröge 2022-10-09 16:06:59 +03:00
parent 7818ac658b
commit 7ee4afacf4
93 changed files with 4004 additions and 5392 deletions

View file

@ -132,13 +132,7 @@ impl ObjectImpl for AudioEcho {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"max-delay" => {
let mut settings = self.settings.lock().unwrap();
@ -164,7 +158,7 @@ impl ObjectImpl for AudioEcho {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"max-delay" => {
let settings = self.settings.lock().unwrap();
@ -236,11 +230,7 @@ impl BaseTransformImpl for AudioEcho {
const PASSTHROUGH_ON_SAME_CAPS: bool = false;
const TRANSFORM_IP_ON_PASSTHROUGH: bool = false;
fn transform_ip(
&self,
_element: &Self::Type,
buf: &mut gst::BufferRef,
) -> Result<gst::FlowSuccess, gst::FlowError> {
fn transform_ip(&self, buf: &mut gst::BufferRef) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut settings = *self.settings.lock().unwrap();
settings.delay = cmp::min(settings.max_delay, settings.delay);
@ -264,12 +254,7 @@ impl BaseTransformImpl for AudioEcho {
Ok(gst::FlowSuccess::Ok)
}
fn set_caps(
&self,
_element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
fn set_caps(&self, incaps: &gst::Caps, outcaps: &gst::Caps) -> Result<(), gst::LoggableError> {
if incaps != outcaps {
return Err(gst::loggable_error!(
CAT,
@ -291,7 +276,7 @@ impl BaseTransformImpl for AudioEcho {
Ok(())
}
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
// Drop state
let _ = self.state.lock().unwrap().take();

View file

@ -218,7 +218,7 @@ impl State {
// Drains all full frames that are currently in the adapter
fn drain_full_frames(
&mut self,
element: &super::AudioLoudNorm,
imp: &AudioLoudNorm,
) -> Result<Vec<gst::Buffer>, gst::FlowError> {
let mut outbufs = vec![];
while self.adapter.available() >= self.info.bpf() as usize * self.current_samples_per_frame
@ -241,7 +241,7 @@ impl State {
.as_slice_of::<f64>()
.map_err(|_| gst::FlowError::Error)?;
let (mut outbuf, pts) = self.process(element, src, pts)?;
let (mut outbuf, pts) = self.process(imp, src, pts)?;
{
let outbuf = outbuf.get_mut().unwrap();
@ -263,8 +263,8 @@ impl State {
}
// Drains everything
fn drain(&mut self, element: &super::AudioLoudNorm) -> Result<gst::Buffer, gst::FlowError> {
gst::debug!(CAT, obj: element, "Draining");
fn drain(&mut self, imp: &AudioLoudNorm) -> Result<gst::Buffer, gst::FlowError> {
gst::debug!(CAT, imp: imp, "Draining");
let (pts, distance) = self.adapter.prev_pts();
let distance_samples = distance / self.info.bpf() as u64;
@ -299,11 +299,11 @@ impl State {
self.frame_type = FrameType::Final;
} else if src.is_empty() {
// Nothing to drain at all
gst::debug!(CAT, obj: element, "No data to drain");
gst::debug!(CAT, imp: imp, "No data to drain");
return Err(gst::FlowError::Eos);
}
let (mut outbuf, pts) = self.process(element, src, pts)?;
let (mut outbuf, pts) = self.process(imp, src, pts)?;
{
let outbuf = outbuf.get_mut().unwrap();
@ -321,10 +321,7 @@ impl State {
Ok(outbuf)
}
fn process_first_frame_is_last(
&mut self,
element: &super::AudioLoudNorm,
) -> Result<(), gst::FlowError> {
fn process_first_frame_is_last(&mut self, imp: &AudioLoudNorm) -> Result<(), gst::FlowError> {
// Calculated loudness in LUFS
let global = self
.r128_in
@ -345,7 +342,7 @@ impl State {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Calculated global loudness for first frame {} with peak {}",
global,
true_peak
@ -371,7 +368,7 @@ impl State {
fn process_first_frame(
&mut self,
element: &super::AudioLoudNorm,
imp: &AudioLoudNorm,
src: &[f64],
pts: impl Into<Option<gst::ClockTime>>,
) -> Result<(gst::Buffer, Option<gst::ClockTime>), gst::FlowError> {
@ -399,7 +396,7 @@ impl State {
self.prev_delta = self.delta[self.index];
gst::debug!(
CAT,
obj: element,
imp: imp,
"Initializing for first frame with gain adjustment of {}",
self.prev_delta
);
@ -430,7 +427,7 @@ impl State {
.as_mut_slice_of::<f64>()
.map_err(|_| gst::FlowError::Error)?;
// This now consumes the first 100ms of limiter_buf for the output.
self.true_peak_limiter(element, dst);
self.true_peak_limiter(imp, dst);
self.r128_out
.add_frames_f64(dst)
.map_err(|_| gst::FlowError::Error)?;
@ -445,7 +442,7 @@ impl State {
Ok((outbuf, pts.into()))
}
fn process_fill_inner_frame(&mut self, element: &super::AudioLoudNorm, src: &[f64]) {
fn process_fill_inner_frame(&mut self, imp: &AudioLoudNorm, src: &[f64]) {
// Get gain for this and the next 100ms frame based the delta array
// and smoothened with a gaussian filter.
let gain = self.gaussian_filter(if self.index + 10 < 30 {
@ -461,7 +458,7 @@ impl State {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Applying gain adjustment {}-{}",
gain,
gain_next
@ -517,7 +514,7 @@ impl State {
fn process_update_gain_inner_frame(
&mut self,
element: &super::AudioLoudNorm,
imp: &AudioLoudNorm,
) -> Result<(), gst::FlowError> {
// Calculate global, shortterm loudness and relative threshold in LUFS.
let global = self
@ -535,7 +532,7 @@ impl State {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Calculated global loudness {}, short term loudness {} and relative threshold {}",
global,
shortterm,
@ -558,7 +555,7 @@ impl State {
self.above_threshold = true;
gst::debug!(
CAT,
obj: element,
imp: imp,
"Above threshold now ({} >= {}, {} > -70)",
shortterm_out,
self.target_i,
@ -586,7 +583,7 @@ impl State {
self.prev_delta = self.delta[self.index];
gst::debug!(
CAT,
obj: element,
imp: imp,
"Calculated new gain adjustment {}",
self.prev_delta
);
@ -601,13 +598,13 @@ impl State {
fn process_inner_frame(
&mut self,
element: &super::AudioLoudNorm,
imp: &AudioLoudNorm,
src: &[f64],
pts: impl Into<Option<gst::ClockTime>>,
) -> Result<(gst::Buffer, Option<gst::ClockTime>), gst::FlowError> {
// Fill in these 100ms and adjust its gain according to previous measurements, and
// at the same time copy 100ms over to the limiter_buf.
self.process_fill_inner_frame(element, src);
self.process_fill_inner_frame(imp, src);
// limiter_buf_index was 100ms advanced above, which brings us to exactly the
// position where we have to start consuming 100ms for the output now, and exactly
@ -625,13 +622,13 @@ impl State {
.as_mut_slice_of::<f64>()
.map_err(|_| gst::FlowError::Error)?;
// This now consumes the next 100ms of limiter_buf for the output.
self.true_peak_limiter(element, dst);
self.true_peak_limiter(imp, dst);
self.r128_out
.add_frames_f64(dst)
.map_err(|_| gst::FlowError::Error)?;
}
self.process_update_gain_inner_frame(element)?;
self.process_update_gain_inner_frame(imp)?;
// PTS is 2.9s seconds before the input PTS as we buffer 3s of samples and just
// outputted here the first 100ms of that.
@ -641,12 +638,7 @@ impl State {
Ok((outbuf, pts))
}
fn process_fill_final_frame(
&mut self,
_element: &super::AudioLoudNorm,
idx: usize,
num_samples: usize,
) {
fn process_fill_final_frame(&mut self, _imp: &AudioLoudNorm, idx: usize, num_samples: usize) {
let channels = self.info.channels() as usize;
// Get gain for this and the next 100ms frame based the delta array
@ -696,7 +688,7 @@ impl State {
fn process_final_frame(
&mut self,
element: &super::AudioLoudNorm,
imp: &AudioLoudNorm,
src: &[f64],
pts: impl Into<Option<gst::ClockTime>>,
) -> Result<(gst::Buffer, Option<gst::ClockTime>), gst::FlowError> {
@ -706,14 +698,14 @@ impl State {
// First process any new/leftover data we get passed. This is the same
// as for inner frames. After this we will have done all gain adjustments
// and all samples we ever output are in buf or limiter_buf.
self.process_fill_inner_frame(element, src);
self.process_fill_inner_frame(imp, src);
// If we got passed less than 100ms in src then limiter_buf_index is now
// not yet at the correct read position! Adjust accordingly here so that all
// further reads come from the right position by copying over the next samples
// from buf.
if num_samples != FRAME_SIZE {
self.process_fill_final_frame(element, num_samples, FRAME_SIZE);
self.process_fill_final_frame(imp, num_samples, FRAME_SIZE);
}
// Now repeatadly run the limiter, output the output gain, update the gains, copy further
@ -744,7 +736,7 @@ impl State {
// self.limiter_buf_index += FRAME_SIZE - num_samples;
//}
self.true_peak_limiter(element, dst);
self.true_peak_limiter(imp, dst);
smp_cnt += frame_size;
if smp_cnt == out_num_samples {
@ -755,11 +747,11 @@ impl State {
self.r128_out
.add_frames_f64(dst)
.map_err(|_| gst::FlowError::Error)?;
self.process_update_gain_inner_frame(element)?;
self.process_update_gain_inner_frame(imp)?;
// And now copy over the next block of samples from buf to limiter_buf
let next_frame_size = std::cmp::min(out_num_samples - smp_cnt, FRAME_SIZE);
self.process_fill_final_frame(element, 0, next_frame_size);
self.process_fill_final_frame(imp, 0, next_frame_size);
// Now for the very last frame we need to update the limiter buffer index by the
// amount of samples the last frame is short to reach the correct read position.
@ -782,7 +774,7 @@ impl State {
fn process_linear_frame(
&mut self,
element: &super::AudioLoudNorm,
imp: &AudioLoudNorm,
src: &[f64],
pts: impl Into<Option<gst::ClockTime>>,
) -> Result<(gst::Buffer, Option<gst::ClockTime>), gst::FlowError> {
@ -790,7 +782,7 @@ impl State {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Applying linear gain adjustment of {}",
self.offset
);
@ -819,7 +811,7 @@ impl State {
fn process(
&mut self,
element: &super::AudioLoudNorm,
imp: &AudioLoudNorm,
src: &[f64],
pts: impl Into<Option<gst::ClockTime>>,
) -> Result<(gst::Buffer, Option<gst::ClockTime>), gst::FlowError> {
@ -833,20 +825,20 @@ impl State {
if self.frame_type == FrameType::First
&& (src.len() / self.info.channels() as usize) < self.current_samples_per_frame as usize
{
self.process_first_frame_is_last(element)?;
self.process_first_frame_is_last(imp)?;
}
match self.frame_type {
FrameType::First => self.process_first_frame(element, src, pts),
FrameType::Inner => self.process_inner_frame(element, src, pts),
FrameType::Final => self.process_final_frame(element, src, pts),
FrameType::Linear => self.process_linear_frame(element, src, pts),
FrameType::First => self.process_first_frame(imp, src, pts),
FrameType::Inner => self.process_inner_frame(imp, src, pts),
FrameType::Final => self.process_final_frame(imp, src, pts),
FrameType::Linear => self.process_linear_frame(imp, src, pts),
}
}
fn true_peak_limiter_out(
&mut self,
element: &super::AudioLoudNorm,
imp: &AudioLoudNorm,
mut smp_cnt: usize,
nb_samples: usize,
) -> usize {
@ -869,7 +861,7 @@ impl State {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Found peak {} at sample {}, going to attack state at sample {} (gain reduction {}-{})",
peak_value,
smp_cnt + LIMITER_ATTACK_WINDOW,
@ -887,7 +879,7 @@ impl State {
fn true_peak_limiter_attack(
&mut self,
element: &super::AudioLoudNorm,
imp: &AudioLoudNorm,
mut smp_cnt: usize,
nb_samples: usize,
) -> usize {
@ -1006,7 +998,7 @@ impl State {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Found new peak {} at sample {}, restarting attack state at sample {} (gain reduction {}-{})",
peak_value,
smp_cnt + LIMITER_ATTACK_WINDOW,
@ -1055,7 +1047,7 @@ impl State {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Found new peak {} at sample {}, adjusting attack state at sample {} (gain reduction {}-{})",
peak_value,
smp_cnt + LIMITER_ATTACK_WINDOW,
@ -1070,7 +1062,7 @@ impl State {
// to ensure that we at least sustain it for that long afterwards.
gst::debug!(
CAT,
obj: element,
imp: imp,
"Found new low peak {} at sample {} in attack state at sample {}",
peak_value,
smp_cnt + LIMITER_ATTACK_WINDOW,
@ -1086,7 +1078,7 @@ impl State {
// If we reached the target gain reduction, go into sustain state.
gst::debug!(
CAT,
obj: element,
imp: imp,
"Going to sustain state at sample {} (gain reduction {})",
smp_cnt,
self.gain_reduction[1]
@ -1100,7 +1092,7 @@ impl State {
fn true_peak_limiter_sustain(
&mut self,
element: &super::AudioLoudNorm,
imp: &AudioLoudNorm,
mut smp_cnt: usize,
nb_samples: usize,
) -> usize {
@ -1165,7 +1157,7 @@ impl State {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Found new peak {} at sample {}, going back to attack state at sample {} (gain reduction {}-{})",
peak_value,
smp_cnt + LIMITER_ATTACK_WINDOW,
@ -1176,7 +1168,7 @@ impl State {
} else {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Found new peak {} at sample {}, going sustain further at sample {} (gain reduction {})",
peak_value,
smp_cnt + LIMITER_ATTACK_WINDOW,
@ -1203,7 +1195,7 @@ impl State {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Going to release state for sample {} at sample {} (gain reduction {}-1.0)",
smp_cnt + LIMITER_RELEASE_WINDOW,
smp_cnt,
@ -1216,7 +1208,7 @@ impl State {
fn true_peak_limiter_release(
&mut self,
element: &super::AudioLoudNorm,
imp: &AudioLoudNorm,
mut smp_cnt: usize,
nb_samples: usize,
) -> usize {
@ -1273,7 +1265,7 @@ impl State {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Found new peak {} at sample {}, going back to attack state at sample {} (gain reduction {}-{})",
peak_value,
smp_cnt + LIMITER_ATTACK_WINDOW,
@ -1285,7 +1277,7 @@ impl State {
self.gain_reduction[1] = current_gain_reduction;
gst::debug!(
CAT,
obj: element,
imp: imp,
"Going from release to sustain state at sample {} because of low peak {} at sample {} (gain reduction {})",
smp_cnt,
peak_value,
@ -1326,7 +1318,7 @@ impl State {
self.limiter_state = LimiterState::Out;
gst::debug!(
CAT,
obj: element,
imp: imp,
"Leaving release state and going to out state at sample {}",
smp_cnt,
);
@ -1335,7 +1327,7 @@ impl State {
smp_cnt
}
fn true_peak_limiter_first_frame(&mut self, element: &super::AudioLoudNorm) {
fn true_peak_limiter_first_frame(&mut self, imp: &AudioLoudNorm) {
let channels = self.info.channels() as usize;
assert_eq!(self.limiter_buf_index, 0);
@ -1364,7 +1356,7 @@ impl State {
self.gain_reduction[1] = self.target_tp / max;
gst::debug!(
CAT,
obj: element,
imp: imp,
"Reducing gain for start of first frame by {} ({} > {}) and going to sustain state",
self.gain_reduction[1],
max,
@ -1376,38 +1368,33 @@ impl State {
}
}
fn true_peak_limiter(&mut self, element: &super::AudioLoudNorm, dst: &mut [f64]) {
fn true_peak_limiter(&mut self, imp: &AudioLoudNorm, dst: &mut [f64]) {
let channels = self.info.channels() as usize;
let nb_samples = dst.len() / channels;
gst::debug!(
CAT,
obj: element,
"Running limiter for {} samples",
nb_samples
);
gst::debug!(CAT, imp: imp, "Running limiter for {} samples", nb_samples);
// For the first frame we can't adjust the gain before it smoothly anymore so instead
// apply the gain reduction immediately if we get above the threshold and move to sustain
// state directly.
if self.frame_type == FrameType::First {
self.true_peak_limiter_first_frame(element);
self.true_peak_limiter_first_frame(imp);
}
let mut smp_cnt = 0;
while smp_cnt < nb_samples {
match self.limiter_state {
LimiterState::Out => {
smp_cnt = self.true_peak_limiter_out(element, smp_cnt, nb_samples);
smp_cnt = self.true_peak_limiter_out(imp, smp_cnt, nb_samples);
}
LimiterState::Attack => {
smp_cnt = self.true_peak_limiter_attack(element, smp_cnt, nb_samples);
smp_cnt = self.true_peak_limiter_attack(imp, smp_cnt, nb_samples);
}
LimiterState::Sustain => {
smp_cnt = self.true_peak_limiter_sustain(element, smp_cnt, nb_samples);
smp_cnt = self.true_peak_limiter_sustain(imp, smp_cnt, nb_samples);
}
LimiterState::Release => {
smp_cnt = self.true_peak_limiter_release(element, smp_cnt, nb_samples);
smp_cnt = self.true_peak_limiter_release(imp, smp_cnt, nb_samples);
}
}
}
@ -1552,15 +1539,14 @@ impl AudioLoudNorm {
fn sink_chain(
&self,
_pad: &gst::Pad,
element: &super::AudioLoudNorm,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: element, "Handling buffer {:?}", buffer);
gst::log!(CAT, imp: self, "Handling buffer {:?}", buffer);
let mut state_guard = self.state.borrow_mut();
let state = match *state_guard {
None => {
gst::error!(CAT, obj: element, "Not negotiated yet");
gst::error!(CAT, imp: self, "Not negotiated yet");
return Err(gst::FlowError::NotNegotiated);
}
Some(ref mut state) => state,
@ -1568,8 +1554,8 @@ impl AudioLoudNorm {
let mut outbufs = vec![];
if buffer.flags().contains(gst::BufferFlags::DISCONT) {
gst::debug!(CAT, obj: element, "Draining on discontinuity");
match state.drain(element) {
gst::debug!(CAT, imp: self, "Draining on discontinuity");
match state.drain(self) {
Ok(outbuf) => {
outbufs.push(outbuf);
}
@ -1582,23 +1568,18 @@ impl AudioLoudNorm {
}
state.adapter.push(buffer);
outbufs.append(&mut state.drain_full_frames(element)?);
outbufs.append(&mut state.drain_full_frames(self)?);
drop(state_guard);
for buffer in outbufs {
gst::log!(CAT, obj: element, "Outputting buffer {:?}", buffer);
gst::log!(CAT, imp: self, "Outputting buffer {:?}", buffer);
self.srcpad.push(buffer)?;
}
Ok(gst::FlowSuccess::Ok)
}
fn sink_event(
&self,
pad: &gst::Pad,
element: &super::AudioLoudNorm,
event: gst::Event,
) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -1619,7 +1600,7 @@ impl AudioLoudNorm {
let mut state = self.state.borrow_mut();
let mut outbuf = None;
if let Some(ref mut state) = &mut *state {
outbuf = match state.drain(element) {
outbuf = match state.drain(self) {
Ok(outbuf) => Some(outbuf),
Err(gst::FlowError::Eos) => None,
Err(_) => return false,
@ -1629,9 +1610,9 @@ impl AudioLoudNorm {
drop(state);
if let Some(outbuf) = outbuf {
gst::log!(CAT, obj: element, "Outputting buffer {:?}", outbuf);
gst::log!(CAT, imp: self, "Outputting buffer {:?}", outbuf);
if let Err(err) = self.srcpad.push(outbuf) {
gst::error!(CAT, obj: element, "Failed to push drained data: {}", err);
gst::error!(CAT, imp: self, "Failed to push drained data: {}", err);
return false;
}
@ -1641,7 +1622,7 @@ impl AudioLoudNorm {
let mut state = self.state.borrow_mut();
let mut outbuf = None;
if let Some(ref mut state) = &mut *state {
outbuf = match state.drain(element) {
outbuf = match state.drain(self) {
Ok(outbuf) => Some(outbuf),
Err(gst::FlowError::Eos) => None,
Err(_) => return false,
@ -1651,11 +1632,11 @@ impl AudioLoudNorm {
drop(state);
if let Some(outbuf) = outbuf {
gst::log!(CAT, obj: element, "Outputting buffer {:?}", outbuf);
gst::log!(CAT, imp: self, "Outputting buffer {:?}", outbuf);
if let Err(err) = self.srcpad.push(outbuf) {
gst::error!(
CAT,
obj: element,
imp: self,
"Failed to push drained data on EOS: {}",
err
);
@ -1678,16 +1659,11 @@ impl AudioLoudNorm {
_ => (),
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
#[allow(clippy::single_match)]
fn src_query(
&self,
pad: &gst::Pad,
element: &super::AudioLoudNorm,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
@ -1706,7 +1682,7 @@ impl AudioLoudNorm {
false
}
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
}
@ -1724,15 +1700,11 @@ impl ObjectSubclass for AudioLoudNorm {
Self::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
|this| this.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
Self::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
)
Self::catch_panic_pad_function(parent, || false, |this| this.sink_event(pad, event))
})
.flags(gst::PadFlags::PROXY_CAPS)
.build();
@ -1740,11 +1712,7 @@ impl ObjectSubclass for AudioLoudNorm {
let templ = klass.pad_template("src").unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
.query_function(|pad, parent, query| {
Self::catch_panic_pad_function(
parent,
|| false,
|this, element| this.src_query(pad, element, query),
)
Self::catch_panic_pad_function(parent, || false, |this| this.src_query(pad, query))
})
.flags(gst::PadFlags::PROXY_CAPS)
.build();
@ -1800,20 +1768,15 @@ impl ObjectImpl for AudioLoudNorm {
PROPERTIES.as_ref()
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"loudness-target" => {
let mut settings = self.settings.lock().unwrap();
@ -1835,7 +1798,7 @@ impl ObjectImpl for AudioLoudNorm {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"loudness-target" => {
let settings = self.settings.lock().unwrap();
@ -1905,10 +1868,9 @@ impl ElementImpl for AudioLoudNorm {
#[allow(clippy::single_match)]
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
let res = self.parent_change_state(element, transition);
let res = self.parent_change_state(transition);
match transition {
gst::StateChange::PausedToReady => {

View file

@ -10,6 +10,7 @@
use gst::glib;
use gst::prelude::*;
use gst::subclass::prelude::*;
use gst_base::prelude::*;
use gst_base::subclass::base_transform::BaseTransformImplExt;
use gst_base::subclass::base_transform::GenerateOutputSuccess;
use gst_base::subclass::prelude::*;
@ -121,7 +122,7 @@ impl State {
}
impl AudioRNNoise {
fn drain(&self, element: &super::AudioRNNoise) -> Result<gst::FlowSuccess, gst::FlowError> {
fn drain(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state_lock = self.state.borrow_mut();
let state = state_lock.as_mut().unwrap();
@ -131,12 +132,7 @@ impl AudioRNNoise {
}
let mut buffer = gst::Buffer::with_size(available).map_err(|e| {
gst::error!(
CAT,
obj: element,
"Failed to allocate buffer at EOS {:?}",
e
);
gst::error!(CAT, imp: self, "Failed to allocate buffer at EOS {:?}", e);
gst::FlowError::Flushing
})?;
@ -158,15 +154,10 @@ impl AudioRNNoise {
state.process(in_data, out_data);
}
let srcpad = element.static_pad("src").unwrap();
srcpad.push(buffer)
self.instance().src_pad().push(buffer)
}
fn generate_output(
&self,
_element: &super::AudioRNNoise,
state: &mut State,
) -> Result<GenerateOutputSuccess, gst::FlowError> {
fn generate_output(&self, state: &mut State) -> Result<GenerateOutputSuccess, gst::FlowError> {
let available = state.adapter.available();
let bpf = state.in_info.bpf() as usize;
let output_size = available - (available % (FRAME_SIZE * bpf));
@ -257,16 +248,11 @@ impl BaseTransformImpl for AudioRNNoise {
const PASSTHROUGH_ON_SAME_CAPS: bool = false;
const TRANSFORM_IP_ON_PASSTHROUGH: bool = false;
fn set_caps(
&self,
element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
fn set_caps(&self, incaps: &gst::Caps, outcaps: &gst::Caps) -> Result<(), gst::LoggableError> {
// Flush previous state
if self.state.borrow_mut().is_some() {
self.drain(element).map_err(|e| {
gst::loggable_error!(CAT, "Error flusing previous state data {:?}", e)
self.drain().map_err(|e| {
gst::loggable_error!(CAT, "Error flushing previous state data {:?}", e)
})?;
}
if incaps != outcaps {
@ -276,7 +262,7 @@ impl BaseTransformImpl for AudioRNNoise {
));
}
gst::debug!(CAT, obj: element, "Set caps to {}", incaps);
gst::debug!(CAT, imp: self, "Set caps to {}", incaps);
let in_info = gst_audio::AudioInfo::from_caps(incaps)
.map_err(|e| gst::loggable_error!(CAT, "Failed to parse input caps {:?}", e))?;
@ -300,22 +286,19 @@ impl BaseTransformImpl for AudioRNNoise {
Ok(())
}
fn generate_output(
&self,
element: &Self::Type,
) -> Result<GenerateOutputSuccess, gst::FlowError> {
fn generate_output(&self) -> Result<GenerateOutputSuccess, gst::FlowError> {
// Check if there are enough data in the queued buffer and adapter,
// if it is not the case, just notify the parent class to not generate
// an output
if let Some(buffer) = self.take_queued_buffer() {
if buffer.flags().contains(gst::BufferFlags::DISCONT) {
self.drain(element)?;
self.drain()?;
}
let mut state_guard = self.state.borrow_mut();
let state = state_guard.as_mut().ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Negotiation,
["Can not generate an output without State"]
);
@ -324,39 +307,33 @@ impl BaseTransformImpl for AudioRNNoise {
state.adapter.push(buffer);
if !state.needs_more_data() {
return self.generate_output(element, state);
return self.generate_output(state);
}
}
Ok(GenerateOutputSuccess::NoOutput)
}
fn sink_event(&self, element: &Self::Type, event: gst::Event) -> bool {
fn sink_event(&self, event: gst::Event) -> bool {
use gst::EventView;
if let EventView::Eos(_) = event.view() {
gst::debug!(CAT, obj: element, "Handling EOS");
if self.drain(element).is_err() {
gst::debug!(CAT, imp: self, "Handling EOS");
if self.drain().is_err() {
return false;
}
}
self.parent_sink_event(element, event)
self.parent_sink_event(event)
}
fn query(
&self,
element: &Self::Type,
direction: gst::PadDirection,
query: &mut gst::QueryRef,
) -> bool {
fn query(&self, direction: gst::PadDirection, query: &mut gst::QueryRef) -> bool {
if direction == gst::PadDirection::Src {
if let gst::QueryViewMut::Latency(q) = query.view_mut() {
let sink_pad = element.static_pad("sink").expect("Sink pad not found");
let mut upstream_query = gst::query::Latency::new();
if sink_pad.peer_query(&mut upstream_query) {
if self.instance().sink_pad().peer_query(&mut upstream_query) {
let (live, mut min, mut max) = upstream_query.result();
gst::debug!(
CAT,
obj: element,
imp: self,
"Peer latency: live {} min {} max {}",
live,
min,
@ -370,10 +347,10 @@ impl BaseTransformImpl for AudioRNNoise {
}
}
}
BaseTransformImplExt::parent_query(self, element, direction, query)
BaseTransformImplExt::parent_query(self, direction, query)
}
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
// Drop state
let _ = self.state.borrow_mut().take();

View file

@ -169,20 +169,14 @@ impl ObjectImpl for EbuR128Level {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"mode" => {
let mode = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing mode from {:?} to {:?}",
settings.mode,
mode
@ -193,7 +187,7 @@ impl ObjectImpl for EbuR128Level {
let post_messages = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing post-messages from {} to {}",
settings.post_messages,
post_messages
@ -205,7 +199,7 @@ impl ObjectImpl for EbuR128Level {
gst::ClockTime::from_nseconds(value.get().expect("type checked upstream"));
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing interval from {} to {}",
settings.interval,
interval,
@ -216,7 +210,7 @@ impl ObjectImpl for EbuR128Level {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"mode" => settings.mode.to_value(),
@ -290,18 +284,13 @@ impl BaseTransformImpl for EbuR128Level {
const PASSTHROUGH_ON_SAME_CAPS: bool = true;
const TRANSFORM_IP_ON_PASSTHROUGH: bool = true;
fn set_caps(
&self,
element: &Self::Type,
incaps: &gst::Caps,
_outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
fn set_caps(&self, incaps: &gst::Caps, _outcaps: &gst::Caps) -> Result<(), gst::LoggableError> {
let info = match gst_audio::AudioInfo::from_caps(incaps) {
Err(_) => return Err(gst::loggable_error!(CAT, "Failed to parse input caps")),
Ok(info) => info,
};
gst::debug!(CAT, obj: element, "Configured for caps {}", incaps,);
gst::debug!(CAT, imp: self, "Configured for caps {}", incaps,);
let settings = *self.settings.lock().unwrap();
@ -364,7 +353,7 @@ impl BaseTransformImpl for EbuR128Level {
val => {
gst::debug!(
CAT,
obj: element,
imp: self,
"Unknown channel position {:?}, ignoring channel",
val
);
@ -402,39 +391,38 @@ impl BaseTransformImpl for EbuR128Level {
Ok(())
}
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
// Drop state
let _ = self.state.borrow_mut().take();
gst::info!(CAT, obj: element, "Stopped");
gst::info!(CAT, imp: self, "Stopped");
Ok(())
}
fn transform_ip_passthrough(
&self,
element: &Self::Type,
buf: &gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let settings = *self.settings.lock().unwrap();
let mut state_guard = self.state.borrow_mut();
let mut state = state_guard.as_mut().ok_or_else(|| {
gst::element_error!(element, gst::CoreError::Negotiation, ["Have no state yet"]);
gst::element_imp_error!(self, gst::CoreError::Negotiation, ["Have no state yet"]);
gst::FlowError::NotNegotiated
})?;
let mut timestamp = buf.pts();
let segment = element.segment().downcast::<gst::ClockTime>().ok();
let segment = self.instance().segment().downcast::<gst::ClockTime>().ok();
let buf = gst_audio::AudioBufferRef::from_buffer_ref_readable(buf, &state.info).map_err(
|_| {
gst::element_error!(element, gst::ResourceError::Read, ["Failed to map buffer"]);
gst::element_imp_error!(self, gst::ResourceError::Read, ["Failed to map buffer"]);
gst::FlowError::Error
},
)?;
let mut frames = Frames::from_audio_buffer(element, &buf)?;
let mut frames = Frames::from_audio_buffer(self, &buf)?;
while frames.num_frames() > 0 {
if self
.reset
@ -459,8 +447,8 @@ impl BaseTransformImpl for EbuR128Level {
frames
.process(to_process, &mut state.ebur128)
.map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to process buffer: {}", err]
);
@ -498,7 +486,7 @@ impl BaseTransformImpl for EbuR128Level {
Ok(loudness) => s.set("momentary-loudness", &loudness),
Err(err) => gst::error!(
CAT,
obj: element,
imp: self,
"Failed to get momentary loudness: {}",
err
),
@ -510,7 +498,7 @@ impl BaseTransformImpl for EbuR128Level {
Ok(loudness) => s.set("shortterm-loudness", &loudness),
Err(err) => gst::error!(
CAT,
obj: element,
imp: self,
"Failed to get shortterm loudness: {}",
err
),
@ -522,7 +510,7 @@ impl BaseTransformImpl for EbuR128Level {
Ok(loudness) => s.set("global-loudness", &loudness),
Err(err) => gst::error!(
CAT,
obj: element,
imp: self,
"Failed to get global loudness: {}",
err
),
@ -532,7 +520,7 @@ impl BaseTransformImpl for EbuR128Level {
Ok(threshold) => s.set("relative-threshold", &threshold),
Err(err) => gst::error!(
CAT,
obj: element,
imp: self,
"Failed to get relative threshold: {}",
err
),
@ -542,12 +530,9 @@ impl BaseTransformImpl for EbuR128Level {
if state.ebur128.mode().contains(ebur128::Mode::LRA) {
match state.ebur128.loudness_range() {
Ok(range) => s.set("loudness-range", &range),
Err(err) => gst::error!(
CAT,
obj: element,
"Failed to get loudness range: {}",
err
),
Err(err) => {
gst::error!(CAT, imp: self, "Failed to get loudness range: {}", err)
}
}
}
@ -559,12 +544,7 @@ impl BaseTransformImpl for EbuR128Level {
match peaks {
Ok(peaks) => s.set("sample-peak", gst::Array::from(peaks)),
Err(err) => {
gst::error!(
CAT,
obj: element,
"Failed to get sample peaks: {}",
err
)
gst::error!(CAT, imp: self, "Failed to get sample peaks: {}", err)
}
}
}
@ -577,24 +557,26 @@ impl BaseTransformImpl for EbuR128Level {
match peaks {
Ok(peaks) => s.set("true-peak", gst::Array::from(peaks)),
Err(err) => {
gst::error!(CAT, obj: element, "Failed to get true peaks: {}", err)
gst::error!(CAT, imp: self, "Failed to get true peaks: {}", err)
}
}
}
gst::debug!(CAT, obj: element, "Posting message {}", s);
gst::debug!(CAT, imp: self, "Posting message {}", s);
let msg = gst::message::Element::builder(s).src(element).build();
let msg = gst::message::Element::builder(s)
.src(&*self.instance())
.build();
// Release lock while posting the message to avoid deadlocks
drop(state_guard);
let _ = element.post_message(msg);
let _ = self.instance().post_message(msg);
state_guard = self.state.borrow_mut();
state = state_guard.as_mut().ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Negotiation,
["Have no state yet"]
);
@ -623,37 +605,37 @@ enum Frames<'a> {
impl<'a> Frames<'a> {
/// Create a new frames wrapper that allows chunked processing.
fn from_audio_buffer(
element: &super::EbuR128Level,
imp: &EbuR128Level,
buf: &'a gst_audio::AudioBufferRef<&'a gst::BufferRef>,
) -> Result<Self, gst::FlowError> {
match (buf.format(), buf.layout()) {
(gst_audio::AUDIO_FORMAT_S16, gst_audio::AudioLayout::Interleaved) => Ok(Frames::S16(
interleaved_channel_data_into_slice(element, buf)?,
interleaved_channel_data_into_slice(imp, buf)?,
buf.channels() as usize,
)),
(gst_audio::AUDIO_FORMAT_S32, gst_audio::AudioLayout::Interleaved) => Ok(Frames::S32(
interleaved_channel_data_into_slice(element, buf)?,
interleaved_channel_data_into_slice(imp, buf)?,
buf.channels() as usize,
)),
(gst_audio::AUDIO_FORMAT_F32, gst_audio::AudioLayout::Interleaved) => Ok(Frames::F32(
interleaved_channel_data_into_slice(element, buf)?,
interleaved_channel_data_into_slice(imp, buf)?,
buf.channels() as usize,
)),
(gst_audio::AUDIO_FORMAT_F64, gst_audio::AudioLayout::Interleaved) => Ok(Frames::F64(
interleaved_channel_data_into_slice(element, buf)?,
interleaved_channel_data_into_slice(imp, buf)?,
buf.channels() as usize,
)),
(gst_audio::AUDIO_FORMAT_S16, gst_audio::AudioLayout::NonInterleaved) => Ok(
Frames::S16P(non_interleaved_channel_data_into_slices(element, buf)?),
Frames::S16P(non_interleaved_channel_data_into_slices(imp, buf)?),
),
(gst_audio::AUDIO_FORMAT_S32, gst_audio::AudioLayout::NonInterleaved) => Ok(
Frames::S32P(non_interleaved_channel_data_into_slices(element, buf)?),
Frames::S32P(non_interleaved_channel_data_into_slices(imp, buf)?),
),
(gst_audio::AUDIO_FORMAT_F32, gst_audio::AudioLayout::NonInterleaved) => Ok(
Frames::F32P(non_interleaved_channel_data_into_slices(element, buf)?),
Frames::F32P(non_interleaved_channel_data_into_slices(imp, buf)?),
),
(gst_audio::AUDIO_FORMAT_F64, gst_audio::AudioLayout::NonInterleaved) => Ok(
Frames::F64P(non_interleaved_channel_data_into_slices(element, buf)?),
Frames::F64P(non_interleaved_channel_data_into_slices(imp, buf)?),
),
_ => Err(gst::FlowError::NotNegotiated),
}
@ -742,36 +724,36 @@ impl<'a> Frames<'a> {
/// Converts an interleaved audio buffer into a typed slice.
fn interleaved_channel_data_into_slice<'a, T: FromByteSlice>(
element: &super::EbuR128Level,
imp: &EbuR128Level,
buf: &'a gst_audio::AudioBufferRef<&gst::BufferRef>,
) -> Result<&'a [T], gst::FlowError> {
buf.plane_data(0)
.map_err(|err| {
gst::error!(CAT, obj: element, "Failed to get audio data: {}", err);
gst::error!(CAT, imp: imp, "Failed to get audio data: {}", err);
gst::FlowError::Error
})?
.as_slice_of::<T>()
.map_err(|err| {
gst::error!(CAT, obj: element, "Failed to handle audio data: {}", err);
gst::error!(CAT, imp: imp, "Failed to handle audio data: {}", err);
gst::FlowError::Error
})
}
/// Converts a non-interleaved audio buffer into a vector of typed slices.
fn non_interleaved_channel_data_into_slices<'a, T: FromByteSlice>(
element: &super::EbuR128Level,
imp: &EbuR128Level,
buf: &'a gst_audio::AudioBufferRef<&gst::BufferRef>,
) -> Result<SmallVec<[&'a [T]; 64]>, gst::FlowError> {
(0..buf.channels())
.map(|c| {
buf.plane_data(c)
.map_err(|err| {
gst::error!(CAT, obj: element, "Failed to get audio data: {}", err);
gst::error!(CAT, imp: imp, "Failed to get audio data: {}", err);
gst::FlowError::Error
})?
.as_slice_of::<T>()
.map_err(|err| {
gst::error!(CAT, obj: element, "Failed to handle audio data: {}", err);
gst::error!(CAT, imp: imp, "Failed to handle audio data: {}", err);
gst::FlowError::Error
})
})

View file

@ -10,6 +10,7 @@ use gst::glib;
use gst::prelude::*;
use gst::subclass::prelude::*;
use gst_base::prelude::*;
use gst_base::subclass::prelude::*;
use hrtf::{HrirSphere, HrtfContext, HrtfProcessor, Vec3};
@ -216,7 +217,6 @@ impl ObjectSubclass for HrtfRender {
impl HrtfRender {
fn process(
&self,
element: &super::HrtfRender,
outbuf: &mut gst::BufferRef,
state: &mut State,
settings: &Settings,
@ -224,7 +224,7 @@ impl HrtfRender {
let mut outbuf =
gst_audio::AudioBufferRef::from_buffer_ref_writable(outbuf, &state.outinfo).map_err(
|err| {
gst::error!(CAT, obj: element, "Failed to map buffer : {}", err);
gst::error!(CAT, imp: self, "Failed to map buffer : {}", err);
gst::FlowError::Error
},
)?;
@ -248,13 +248,13 @@ impl HrtfRender {
while state.adapter.available() >= inblksz {
let inbuf = state.adapter.take_buffer(inblksz).map_err(|_| {
gst::error!(CAT, obj: element, "Failed to map buffer");
gst::error!(CAT, imp: self, "Failed to map buffer");
gst::FlowError::Error
})?;
let inbuf = gst_audio::AudioBuffer::from_buffer_readable(inbuf, &state.ininfo)
.map_err(|_| {
gst::error!(CAT, obj: element, "Failed to map buffer");
gst::error!(CAT, imp: self, "Failed to map buffer");
gst::FlowError::Error
})?;
@ -326,7 +326,7 @@ impl HrtfRender {
Ok(gst::FlowSuccess::Ok)
}
fn drain(&self, element: &super::HrtfRender) -> Result<gst::FlowSuccess, gst::FlowError> {
fn drain(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
let settings = &self.settings.lock().unwrap();
let mut state_guard = self.state.lock().unwrap();
@ -384,19 +384,17 @@ impl HrtfRender {
let mut outbuf = gst::Buffer::with_size(outblksz).map_err(|_| gst::FlowError::Error)?;
let outbuf_mut = outbuf.get_mut().unwrap();
self.process(element, outbuf_mut, state, settings)?;
self.process(outbuf_mut, state, settings)?;
outbuf_mut.set_size(outputsz);
outbuf_mut.set_pts(pts);
outbuf_mut.set_offset(offset);
outbuf_mut.set_duration(duration);
let srcpad = element.static_pad("src").unwrap();
state.reset_processors();
drop(state_guard);
srcpad.push(outbuf)
self.instance().src_pad().push(outbuf)
}
}
@ -445,13 +443,7 @@ impl ObjectImpl for HrtfRender {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"hrir-raw" => {
let mut settings = self.settings.lock().unwrap();
@ -502,7 +494,7 @@ impl ObjectImpl for HrtfRender {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"hrir-raw" => {
let settings = self.settings.lock().unwrap();
@ -600,7 +592,6 @@ impl BaseTransformImpl for HrtfRender {
fn transform(
&self,
element: &Self::Type,
inbuf: &gst::Buffer,
outbuf: &mut gst::BufferRef,
) -> Result<gst::FlowSuccess, gst::FlowError> {
@ -612,7 +603,7 @@ impl BaseTransformImpl for HrtfRender {
state.adapter.push(inbuf.clone());
if state.adapter.available() >= state.input_block_size() {
return self.process(element, outbuf, state, settings);
return self.process(outbuf, state, settings);
}
Ok(gst::FlowSuccess::Ok)
@ -620,7 +611,6 @@ impl BaseTransformImpl for HrtfRender {
fn transform_size(
&self,
element: &Self::Type,
_direction: gst::PadDirection,
_caps: &gst::Caps,
size: usize,
@ -638,7 +628,7 @@ impl BaseTransformImpl for HrtfRender {
gst::log!(
CAT,
obj: element,
imp: self,
"Adapter size: {}, input size {}, transformed size {}",
state.adapter.available(),
size,
@ -650,7 +640,6 @@ impl BaseTransformImpl for HrtfRender {
fn transform_caps(
&self,
element: &Self::Type,
direction: gst::PadDirection,
caps: &gst::Caps,
filter: Option<&gst::Caps>,
@ -685,7 +674,7 @@ impl BaseTransformImpl for HrtfRender {
gst::debug!(
CAT,
obj: element,
imp: self,
"Transformed caps from {} to {} in direction {:?}",
caps,
other_caps,
@ -695,12 +684,7 @@ impl BaseTransformImpl for HrtfRender {
Some(other_caps)
}
fn set_caps(
&self,
element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
fn set_caps(&self, incaps: &gst::Caps, outcaps: &gst::Caps) -> Result<(), gst::LoggableError> {
let ininfo = gst_audio::AudioInfo::from_caps(incaps)
.map_err(|_| gst::loggable_error!(CAT, "Failed to parse input caps"))?;
@ -761,15 +745,15 @@ impl BaseTransformImpl for HrtfRender {
adapter: gst_base::UniqueAdapter::new(),
});
gst::debug!(CAT, obj: element, "Configured for caps {}", incaps);
gst::debug!(CAT, imp: self, "Configured for caps {}", incaps);
Ok(())
}
fn sink_event(&self, element: &Self::Type, event: gst::Event) -> bool {
fn sink_event(&self, event: gst::Event) -> bool {
use gst::EventView;
gst::debug!(CAT, "Handling event {:?}", event);
gst::debug!(CAT, imp: self, "Handling event {:?}", event);
match event.view() {
EventView::FlushStop(_) => {
@ -782,10 +766,10 @@ impl BaseTransformImpl for HrtfRender {
}
}
EventView::Eos(_) => {
if self.drain(element).is_err() {
if self.drain().is_err() {
gst::warning!(CAT, "Failed to drain internal buffer");
gst::element_warning!(
element,
gst::element_imp_warning!(
self,
gst::CoreError::Event,
["Failed to drain internal buffer"]
);
@ -794,10 +778,10 @@ impl BaseTransformImpl for HrtfRender {
_ => {}
}
self.parent_sink_event(element, event)
self.parent_sink_event(event)
}
fn start(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
// get global thread pool
let mut thread_pool_g = THREAD_POOL.lock().unwrap();
let mut thread_pool = self.thread_pool.lock().unwrap();
@ -821,7 +805,7 @@ impl BaseTransformImpl for HrtfRender {
Ok(())
}
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
// Drop state
let _ = self.state.lock().unwrap().take();
// Drop thread pool

View file

@ -102,20 +102,20 @@ impl ElementImpl for ClaxonDec {
}
impl AudioDecoderImpl for ClaxonDec {
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = None;
Ok(())
}
fn start(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = Some(State { audio_info: None });
Ok(())
}
fn set_format(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
gst::debug!(CAT, obj: element, "Setting format {:?}", caps);
fn set_format(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
gst::debug!(CAT, imp: self, "Setting format {:?}", caps);
let mut audio_info: Option<gst_audio::AudioInfo> = None;
@ -124,28 +124,25 @@ impl AudioDecoderImpl for ClaxonDec {
let streamheaders = streamheaders.as_slice();
if streamheaders.len() < 2 {
gst::debug!(
CAT,
obj: element,
"Not enough streamheaders, trying in-band"
);
gst::debug!(CAT, imp: self, "Not enough streamheaders, trying in-band");
} else {
let ident_buf = streamheaders[0].get::<Option<gst::Buffer>>();
if let Ok(Some(ident_buf)) = ident_buf {
gst::debug!(CAT, obj: element, "Got streamheader buffers");
gst::debug!(CAT, imp: self, "Got streamheader buffers");
let inmap = ident_buf.map_readable().unwrap();
if inmap[0..7] != [0x7f, b'F', b'L', b'A', b'C', 0x01, 0x00] {
gst::debug!(CAT, obj: element, "Unknown streamheader format");
gst::debug!(CAT, imp: self, "Unknown streamheader format");
} else if let Ok(tstreaminfo) = claxon_streaminfo(&inmap[13..]) {
if let Ok(taudio_info) = gstaudioinfo(&tstreaminfo) {
// To speed up negotiation
let element = self.instance();
if element.set_output_format(&taudio_info).is_err()
|| element.negotiate().is_err()
{
gst::debug!(
CAT,
obj: element,
imp: self,
"Error to negotiate output from based on in-caps streaminfo"
);
}
@ -166,10 +163,9 @@ impl AudioDecoderImpl for ClaxonDec {
#[allow(clippy::verbose_bit_mask)]
fn handle_frame(
&self,
element: &Self::Type,
inbuf: Option<&gst::Buffer>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::debug!(CAT, obj: element, "Handling buffer {:?}", inbuf);
gst::debug!(CAT, imp: self, "Handling buffer {:?}", inbuf);
let inbuf = match inbuf {
None => return Ok(gst::FlowSuccess::Ok),
@ -177,7 +173,7 @@ impl AudioDecoderImpl for ClaxonDec {
};
let inmap = inbuf.map_readable().map_err(|_| {
gst::error!(CAT, obj: element, "Failed to buffer readable");
gst::error!(CAT, imp: self, "Failed to buffer readable");
gst::FlowError::Error
})?;
@ -185,51 +181,51 @@ impl AudioDecoderImpl for ClaxonDec {
let state = state_guard.as_mut().ok_or(gst::FlowError::NotNegotiated)?;
if inmap.as_slice() == b"fLaC" {
gst::debug!(CAT, obj: element, "fLaC buffer received");
gst::debug!(CAT, imp: self, "fLaC buffer received");
} else if inmap[0] & 0x7F == 0x00 {
gst::debug!(CAT, obj: element, "Streaminfo header buffer received");
return self.handle_streaminfo_header(element, state, inmap.as_ref());
gst::debug!(CAT, imp: self, "Streaminfo header buffer received");
return self.handle_streaminfo_header(state, inmap.as_ref());
} else if inmap[0] == 0b1111_1111 && inmap[1] & 0b1111_1100 == 0b1111_1000 {
gst::debug!(CAT, obj: element, "Data buffer received");
return self.handle_data(element, state, inmap.as_ref());
gst::debug!(CAT, imp: self, "Data buffer received");
return self.handle_data(state, inmap.as_ref());
} else {
// info about other headers in flacparse and https://xiph.org/flac/format.html
gst::debug!(
CAT,
obj: element,
imp: self,
"Other header buffer received {:?}",
inmap[0] & 0x7F
);
}
element.finish_frame(None, 1)
self.instance().finish_frame(None, 1)
}
}
impl ClaxonDec {
fn handle_streaminfo_header(
&self,
element: &super::ClaxonDec,
state: &mut State,
indata: &[u8],
) -> Result<gst::FlowSuccess, gst::FlowError> {
let streaminfo = claxon_streaminfo(indata).map_err(|e| {
gst::element_error!(element, gst::StreamError::Decode, [e]);
gst::element_imp_error!(self, gst::StreamError::Decode, [e]);
gst::FlowError::Error
})?;
let audio_info = gstaudioinfo(&streaminfo).map_err(|e| {
gst::element_error!(element, gst::StreamError::Decode, [&e]);
gst::element_imp_error!(self, gst::StreamError::Decode, [&e]);
gst::FlowError::Error
})?;
gst::debug!(
CAT,
obj: element,
imp: self,
"Successfully parsed headers: {:?}",
audio_info
);
let element = self.instance();
element.set_output_format(&audio_info)?;
element.negotiate()?;
@ -240,7 +236,6 @@ impl ClaxonDec {
fn handle_data(
&self,
element: &super::ClaxonDec,
state: &mut State,
indata: &[u8],
) -> Result<gst::FlowSuccess, gst::FlowError> {
@ -265,10 +260,10 @@ impl ClaxonDec {
let mut reader = claxon::frame::FrameReader::new(&mut cursor);
let result = match reader.read_next_or_eof(buffer) {
Ok(Some(result)) => result,
Ok(None) => return element.finish_frame(None, 1),
Ok(None) => return self.instance().finish_frame(None, 1),
Err(err) => {
return gst_audio::audio_decoder_error!(
element,
self.instance(),
1,
gst::StreamError::Decode,
["Failed to decode packet: {:?}", err]
@ -293,7 +288,7 @@ impl ClaxonDec {
let depth_adjusted = depth.adjust_samples(v);
let outbuf = gst::Buffer::from_mut_slice(depth_adjusted);
element.finish_frame(Some(outbuf), 1)
self.instance().finish_frame(Some(outbuf), 1)
}
}

View file

@ -9,7 +9,8 @@
use gst::glib;
use gst::prelude::*;
use gst::subclass::prelude::*;
use gst::{element_error, error_msg, loggable_error};
use gst::{element_imp_error, error_msg, loggable_error};
use gst_base::prelude::*;
use gst_base::subclass::base_transform::GenerateOutputSuccess;
use gst_base::subclass::prelude::*;
@ -170,7 +171,7 @@ impl CsoundFilter {
}
}
fn drain(&self, element: &super::CsoundFilter) -> Result<gst::FlowSuccess, gst::FlowError> {
fn drain(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
let csound = self.csound.lock().unwrap();
let mut state_lock = self.state.lock().unwrap();
let state = state_lock.as_mut().unwrap();
@ -191,12 +192,7 @@ impl CsoundFilter {
(avail / state.in_info.channels() as usize) * state.out_info.channels() as usize;
let mut buffer = gst::Buffer::with_size(out_bytes).map_err(|e| {
gst::error!(
CAT,
obj: element,
"Failed to allocate buffer at EOS {:?}",
e
);
gst::error!(CAT, imp: self, "Failed to allocate buffer at EOS {:?}", e);
gst::FlowError::Flushing
})?;
@ -208,8 +204,6 @@ impl CsoundFilter {
buffer_mut.set_pts(pts);
buffer_mut.set_duration(duration);
let srcpad = element.static_pad("src").unwrap();
let adapter_map = state.adapter.map(avail).unwrap();
let data = adapter_map
.as_ref()
@ -236,14 +230,10 @@ impl CsoundFilter {
drop(state_lock);
drop(csound);
srcpad.push(buffer)
self.instance().src_pad().push(buffer)
}
fn generate_output(
&self,
element: &super::CsoundFilter,
state: &mut State,
) -> Result<GenerateOutputSuccess, gst::FlowError> {
fn generate_output(&self, state: &mut State) -> Result<GenerateOutputSuccess, gst::FlowError> {
let output_size = state.max_output_size(state.adapter.available());
let mut output = gst::Buffer::with_size(output_size).map_err(|_| gst::FlowError::Error)?;
@ -257,7 +247,7 @@ impl CsoundFilter {
gst::log!(
CAT,
obj: element,
imp: self,
"Generating output at: {} - duration: {}",
pts.display(),
duration.display(),
@ -367,13 +357,7 @@ impl ObjectImpl for CsoundFilter {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"loop" => {
let mut settings = self.settings.lock().unwrap();
@ -405,7 +389,7 @@ impl ObjectImpl for CsoundFilter {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"loop" => {
let settings = self.settings.lock().unwrap();
@ -478,7 +462,7 @@ impl BaseTransformImpl for CsoundFilter {
const PASSTHROUGH_ON_SAME_CAPS: bool = false;
const TRANSFORM_IP_ON_PASSTHROUGH: bool = false;
fn start(&self, _element: &Self::Type) -> std::result::Result<(), gst::ErrorMessage> {
fn start(&self) -> std::result::Result<(), gst::ErrorMessage> {
self.compile_score()?;
let csound = self.csound.lock().unwrap();
@ -492,32 +476,31 @@ impl BaseTransformImpl for CsoundFilter {
Ok(())
}
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
let csound = self.csound.lock().unwrap();
csound.stop();
csound.reset();
let _ = self.state.lock().unwrap().take();
gst::info!(CAT, obj: element, "Stopped");
gst::info!(CAT, imp: self, "Stopped");
Ok(())
}
fn sink_event(&self, element: &Self::Type, event: gst::Event) -> bool {
fn sink_event(&self, event: gst::Event) -> bool {
use gst::EventView;
if let EventView::Eos(_) = event.view() {
gst::log!(CAT, obj: element, "Handling Eos");
if self.drain(element).is_err() {
gst::log!(CAT, imp: self, "Handling Eos");
if self.drain().is_err() {
return false;
}
}
self.parent_sink_event(element, event)
self.parent_sink_event(event)
}
fn transform_caps(
&self,
element: &Self::Type,
direction: gst::PadDirection,
caps: &gst::Caps,
filter: Option<&gst::Caps>,
@ -553,7 +536,7 @@ impl BaseTransformImpl for CsoundFilter {
gst::debug!(
CAT,
obj: element,
imp: self,
"Transformed caps from {} to {} in direction {:?}",
caps,
other_caps,
@ -567,15 +550,10 @@ impl BaseTransformImpl for CsoundFilter {
Some(other_caps)
}
fn set_caps(
&self,
element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
fn set_caps(&self, incaps: &gst::Caps, outcaps: &gst::Caps) -> Result<(), gst::LoggableError> {
// Flush previous state
if self.state.lock().unwrap().is_some() {
self.drain(element)
self.drain()
.map_err(|e| loggable_error!(CAT, "Error flusing previous state data {:?}", e))?;
}
@ -626,22 +604,19 @@ impl BaseTransformImpl for CsoundFilter {
Ok(())
}
fn generate_output(
&self,
element: &Self::Type,
) -> Result<GenerateOutputSuccess, gst::FlowError> {
fn generate_output(&self) -> Result<GenerateOutputSuccess, gst::FlowError> {
// Check if there are enough data in the queued buffer and adapter,
// if it is not the case, just notify the parent class to not generate
// an output
if let Some(buffer) = self.take_queued_buffer() {
if buffer.flags().contains(gst::BufferFlags::DISCONT) {
self.drain(element)?;
self.drain()?;
}
let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().ok_or_else(|| {
element_error!(
element,
element_imp_error!(
self,
gst::CoreError::Negotiation,
["Can not generate an output without State"]
);
@ -650,7 +625,7 @@ impl BaseTransformImpl for CsoundFilter {
state.adapter.push(buffer);
if !state.needs_more_data() {
return self.generate_output(element, state);
return self.generate_output(state);
}
}
gst::log!(CAT, "No enough data to generate output");

View file

@ -103,13 +103,13 @@ impl ElementImpl for LewtonDec {
}
impl AudioDecoderImpl for LewtonDec {
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = None;
Ok(())
}
fn start(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = Some(State {
header_bufs: (None, None, None),
headerset: None,
@ -121,8 +121,8 @@ impl AudioDecoderImpl for LewtonDec {
Ok(())
}
fn set_format(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
gst::debug!(CAT, obj: element, "Setting format {:?}", caps);
fn set_format(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
gst::debug!(CAT, imp: self, "Setting format {:?}", caps);
// When the caps are changing we require new headers
let mut state_guard = self.state.borrow_mut();
@ -140,11 +140,7 @@ impl AudioDecoderImpl for LewtonDec {
if let Ok(Some(streamheaders)) = s.get_optional::<gst::ArrayRef>("streamheader") {
let streamheaders = streamheaders.as_slice();
if streamheaders.len() < 3 {
gst::debug!(
CAT,
obj: element,
"Not enough streamheaders, trying in-band"
);
gst::debug!(CAT, imp: self, "Not enough streamheaders, trying in-band");
return Ok(());
}
@ -154,7 +150,7 @@ impl AudioDecoderImpl for LewtonDec {
if let (Ok(Some(ident_buf)), Ok(Some(comment_buf)), Ok(Some(setup_buf))) =
(ident_buf, comment_buf, setup_buf)
{
gst::debug!(CAT, obj: element, "Got streamheader buffers");
gst::debug!(CAT, imp: self, "Got streamheader buffers");
state.header_bufs = (Some(ident_buf), Some(comment_buf), Some(setup_buf));
}
}
@ -162,8 +158,8 @@ impl AudioDecoderImpl for LewtonDec {
Ok(())
}
fn flush(&self, element: &Self::Type, _hard: bool) {
gst::debug!(CAT, obj: element, "Flushing");
fn flush(&self, _hard: bool) {
gst::debug!(CAT, imp: self, "Flushing");
let mut state_guard = self.state.borrow_mut();
if let Some(ref mut state) = *state_guard {
@ -173,10 +169,9 @@ impl AudioDecoderImpl for LewtonDec {
fn handle_frame(
&self,
element: &Self::Type,
inbuf: Option<&gst::Buffer>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::debug!(CAT, obj: element, "Handling buffer {:?}", inbuf);
gst::debug!(CAT, imp: self, "Handling buffer {:?}", inbuf);
let inbuf = match inbuf {
None => return Ok(gst::FlowSuccess::Ok),
@ -184,7 +179,7 @@ impl AudioDecoderImpl for LewtonDec {
};
let inmap = inbuf.map_readable().map_err(|_| {
gst::error!(CAT, obj: element, "Failed to buffer readable");
gst::error!(CAT, imp: self, "Failed to buffer readable");
gst::FlowError::Error
})?;
@ -193,48 +188,47 @@ impl AudioDecoderImpl for LewtonDec {
// Ignore empty packets unless we have no headers yet
if inmap.len() == 0 {
element.finish_frame(None, 1)?;
self.instance().finish_frame(None, 1)?;
if state.headerset.is_some() {
return Ok(gst::FlowSuccess::Ok);
} else {
gst::error!(CAT, obj: element, "Got empty packet before all headers");
gst::error!(CAT, imp: self, "Got empty packet before all headers");
return Err(gst::FlowError::Error);
}
}
// If this is a header packet then handle it
if inmap[0] & 0x01 == 0x01 {
return self.handle_header(element, state, inbuf, inmap.as_ref());
return self.handle_header(state, inbuf, inmap.as_ref());
}
// If it's a data packet then try to initialize the headerset now if we didn't yet
if state.headerset.is_none() {
self.initialize(element, state)?;
self.initialize(state)?;
}
self.handle_data(element, state, inmap.as_ref())
self.handle_data(state, inmap.as_ref())
}
}
impl LewtonDec {
fn handle_header(
&self,
element: &super::LewtonDec,
state: &mut State,
inbuf: &gst::Buffer,
indata: &[u8],
) -> Result<gst::FlowSuccess, gst::FlowError> {
// ident header
if indata[0] == 0x01 {
gst::debug!(CAT, obj: element, "Got ident header buffer");
gst::debug!(CAT, imp: self, "Got ident header buffer");
state.header_bufs = (Some(inbuf.clone()), None, None);
} else if indata[0] == 0x03 {
// comment header
if state.header_bufs.0.is_none() {
gst::warning!(CAT, obj: element, "Got comment header before ident header");
gst::warning!(CAT, imp: self, "Got comment header before ident header");
} else {
gst::debug!(CAT, obj: element, "Got comment header buffer");
gst::debug!(CAT, imp: self, "Got comment header buffer");
state.header_bufs.1 = Some(inbuf.clone());
}
} else if indata[0] == 0x05 {
@ -242,30 +236,26 @@ impl LewtonDec {
if state.header_bufs.0.is_none() || state.header_bufs.1.is_none() {
gst::warning!(
CAT,
obj: element,
imp: self,
"Got setup header before ident/comment header"
);
} else {
gst::debug!(CAT, obj: element, "Got setup header buffer");
gst::debug!(CAT, imp: self, "Got setup header buffer");
state.header_bufs.2 = Some(inbuf.clone());
}
}
element.finish_frame(None, 1)
self.instance().finish_frame(None, 1)
}
fn initialize(
&self,
element: &super::LewtonDec,
state: &mut State,
) -> Result<(), gst::FlowError> {
fn initialize(&self, state: &mut State) -> Result<(), gst::FlowError> {
let (ident_buf, comment_buf, setup_buf) = match state.header_bufs {
(Some(ref ident_buf), Some(ref comment_buf), Some(ref setup_buf)) => {
(ident_buf, comment_buf, setup_buf)
}
_ => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Got no headers before data packets"]
);
@ -275,12 +265,12 @@ impl LewtonDec {
// First try to parse the headers
let ident_map = ident_buf.map_readable().map_err(|_| {
gst::error!(CAT, obj: element, "Failed to map ident buffer readable");
gst::error!(CAT, imp: self, "Failed to map ident buffer readable");
gst::FlowError::Error
})?;
let ident = lewton::header::read_header_ident(ident_map.as_ref()).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Failed to parse ident header: {:?}", err]
);
@ -288,12 +278,12 @@ impl LewtonDec {
})?;
let comment_map = comment_buf.map_readable().map_err(|_| {
gst::error!(CAT, obj: element, "Failed to map comment buffer readable");
gst::error!(CAT, imp: self, "Failed to map comment buffer readable");
gst::FlowError::Error
})?;
let comment = lewton::header::read_header_comment(comment_map.as_ref()).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Failed to parse comment header: {:?}", err]
);
@ -301,7 +291,7 @@ impl LewtonDec {
})?;
let setup_map = setup_buf.map_readable().map_err(|_| {
gst::error!(CAT, obj: element, "Failed to map setup buffer readable");
gst::error!(CAT, imp: self, "Failed to map setup buffer readable");
gst::FlowError::Error
})?;
let setup = lewton::header::read_header_setup(
@ -310,8 +300,8 @@ impl LewtonDec {
(ident.blocksize_0, ident.blocksize_1),
)
.map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Failed to parse setup header: {:?}", err]
);
@ -339,7 +329,7 @@ impl LewtonDec {
if gst_audio::channel_reorder_map(from, to, &mut map[..channels]).is_err() {
gst::error!(
CAT,
obj: element,
imp: self,
"Failed to generate channel reorder map from {:?} to {:?}",
from,
to,
@ -355,7 +345,7 @@ impl LewtonDec {
gst::debug!(
CAT,
obj: element,
imp: self,
"Successfully parsed headers: {:?}",
audio_info
);
@ -363,15 +353,14 @@ impl LewtonDec {
state.audio_info = Some(audio_info.clone());
state.reorder_map = reorder_map;
element.set_output_format(&audio_info)?;
element.negotiate()?;
self.instance().set_output_format(&audio_info)?;
self.instance().negotiate()?;
Ok(())
}
fn handle_data(
&self,
element: &super::LewtonDec,
state: &mut State,
indata: &[u8],
) -> Result<gst::FlowSuccess, gst::FlowError> {
@ -387,7 +376,7 @@ impl LewtonDec {
Ok(decoded) => decoded,
Err(err) => {
return audio_decoder_error!(
element,
self.instance(),
1,
gst::StreamError::Decode,
["Failed to decode packet: {:?}", err]
@ -397,7 +386,7 @@ impl LewtonDec {
if decoded.channel_count != audio_info.channels() as usize {
return audio_decoder_error!(
element,
self.instance(),
1,
gst::StreamError::Decode,
[
@ -409,18 +398,19 @@ impl LewtonDec {
}
let sample_count = decoded.samples.len() / audio_info.channels() as usize;
gst::debug!(CAT, obj: element, "Got {} decoded samples", sample_count);
gst::debug!(CAT, imp: self, "Got {} decoded samples", sample_count);
if sample_count == 0 {
return element.finish_frame(None, 1);
return self.instance().finish_frame(None, 1);
}
let outbuf = if let Some(ref reorder_map) = state.reorder_map {
let mut outbuf = element
let mut outbuf = self
.instance()
.allocate_output_buffer(sample_count as usize * audio_info.bpf() as usize)
.map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Failed to allocate output buffer"]
);
@ -431,8 +421,8 @@ impl LewtonDec {
// GStreamer channel order
let outbuf = outbuf.get_mut().unwrap();
let mut outmap = outbuf.map_writable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Failed to map output buffer writable"]
);
@ -471,7 +461,7 @@ impl LewtonDec {
gst::Buffer::from_mut_slice(CastVec(decoded.samples))
};
element.finish_frame(Some(outbuf), 1)
self.instance().finish_frame(Some(outbuf), 1)
}
}

View file

@ -130,13 +130,7 @@ impl ObjectImpl for SpotifyAudioSrc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"username" => {
let mut settings = self.settings.lock().unwrap();
@ -166,7 +160,7 @@ impl ObjectImpl for SpotifyAudioSrc {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"username" => {
let settings = self.settings.lock().unwrap();
@ -233,7 +227,7 @@ impl ElementImpl for SpotifyAudioSrc {
}
impl BaseSrcImpl for SpotifyAudioSrc {
fn start(&self, src: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
{
let state = self.state.lock().unwrap();
if state.is_some() {
@ -244,17 +238,17 @@ impl BaseSrcImpl for SpotifyAudioSrc {
if let Err(err) = RUNTIME.block_on(async move { self.setup().await }) {
let details = format!("{:?}", err);
gst::error!(CAT, obj: src, "failed to start: {}", details);
gst::element_error!(src, gst::ResourceError::Settings, [&details]);
gst::error!(CAT, imp: self, "failed to start: {}", details);
gst::element_imp_error!(self, gst::ResourceError::Settings, [&details]);
return Err(gst::error_msg!(gst::ResourceError::Settings, [&details]));
}
Ok(())
}
fn stop(&self, src: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
if let Some(state) = self.state.lock().unwrap().take() {
gst::debug!(CAT, obj: src, "stopping");
gst::debug!(CAT, imp: self, "stopping");
state.player.stop();
state.player_channel_handle.abort();
// FIXME: not sure why this is needed to unblock BufferSink::write(), dropping State should drop the receiver
@ -266,7 +260,6 @@ impl BaseSrcImpl for SpotifyAudioSrc {
fn create(
&self,
src: &Self::Type,
_offset: u64,
_buffer: Option<&mut gst::BufferRef>,
_length: u32,
@ -276,17 +269,17 @@ impl BaseSrcImpl for SpotifyAudioSrc {
match state.receiver.recv().unwrap() {
Message::Buffer(buffer) => {
gst::log!(CAT, obj: src, "got buffer of size {}", buffer.size());
gst::log!(CAT, imp: self, "got buffer of size {}", buffer.size());
Ok(CreateSuccess::NewBuffer(buffer))
}
Message::Eos => {
gst::debug!(CAT, obj: src, "eos");
gst::debug!(CAT, imp: self, "eos");
Err(gst::FlowError::Eos)
}
Message::Unavailable => {
gst::error!(CAT, obj: src, "track is not available");
gst::element_error!(
src,
gst::error!(CAT, imp: self, "track is not available");
gst::element_imp_error!(
self,
gst::ResourceError::NotFound,
["track is not available"]
);
@ -298,8 +291,6 @@ impl BaseSrcImpl for SpotifyAudioSrc {
impl SpotifyAudioSrc {
async fn setup(&self) -> anyhow::Result<()> {
let src = self.instance();
let (credentials, cache, track) = {
let settings = self.settings.lock().unwrap();
@ -325,11 +316,11 @@ impl SpotifyAudioSrc {
let credentials = match cache.credentials() {
Some(cached_cred) => {
gst::debug!(CAT, obj: &src, "reuse credentials from cache",);
gst::debug!(CAT, imp: self, "reuse credentials from cache",);
cached_cred
}
None => {
gst::debug!(CAT, obj: &src, "credentials not in cache",);
gst::debug!(CAT, imp: self, "credentials not in cache",);
if settings.username.is_empty() {
bail!("username is not set and credentials are not in cache");

View file

@ -65,11 +65,7 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
impl FileSink {
fn set_location(
&self,
element: &super::FileSink,
location: Option<FileLocation>,
) -> Result<(), glib::Error> {
fn set_location(&self, location: Option<FileLocation>) -> Result<(), glib::Error> {
let state = self.state.lock().unwrap();
if let State::Started { .. } = *state {
return Err(glib::Error::new(
@ -85,20 +81,20 @@ impl FileSink {
Some(ref location_cur) => {
gst::info!(
CAT,
obj: element,
imp: self,
"Changing `location` from {:?} to {}",
location_cur,
location,
);
}
None => {
gst::info!(CAT, obj: element, "Setting `location` to {}", location,);
gst::info!(CAT, imp: self, "Setting `location` to {}", location,);
}
}
Some(location)
}
None => {
gst::info!(CAT, obj: element, "Resetting `location` to None",);
gst::info!(CAT, imp: self, "Resetting `location` to None",);
None
}
};
@ -127,31 +123,25 @@ impl ObjectImpl for FileSink {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"location" => {
let res = match value.get::<Option<String>>() {
Ok(Some(location)) => FileLocation::try_from_path_str(location)
.and_then(|file_location| self.set_location(obj, Some(file_location))),
Ok(None) => self.set_location(obj, None),
.and_then(|file_location| self.set_location(Some(file_location))),
Ok(None) => self.set_location(None),
Err(_) => unreachable!("type checked upstream"),
};
if let Err(err) = res {
gst::error!(CAT, obj: obj, "Failed to set property `location`: {}", err);
gst::error!(CAT, imp: self, "Failed to set property `location`: {}", err);
}
}
_ => unimplemented!(),
};
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"location" => {
let settings = self.settings.lock().unwrap();
@ -202,7 +192,7 @@ impl ElementImpl for FileSink {
}
impl BaseSinkImpl for FileSink {
fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
let mut state = self.state.lock().unwrap();
if let State::Started { .. } = *state {
unreachable!("FileSink already started");
@ -226,15 +216,15 @@ impl BaseSinkImpl for FileSink {
]
)
})?;
gst::debug!(CAT, obj: element, "Opened file {:?}", file);
gst::debug!(CAT, imp: self, "Opened file {:?}", file);
*state = State::Started { file, position: 0 };
gst::info!(CAT, obj: element, "Started");
gst::info!(CAT, imp: self, "Started");
Ok(())
}
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
let mut state = self.state.lock().unwrap();
if let State::Stopped = *state {
return Err(gst::error_msg!(
@ -244,18 +234,14 @@ impl BaseSinkImpl for FileSink {
}
*state = State::Stopped;
gst::info!(CAT, obj: element, "Stopped");
gst::info!(CAT, imp: self, "Stopped");
Ok(())
}
// TODO: implement seek in BYTES format
fn render(
&self,
element: &Self::Type,
buffer: &gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
fn render(&self, buffer: &gst::Buffer) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state = self.state.lock().unwrap();
let (file, position) = match *state {
State::Started {
@ -263,20 +249,20 @@ impl BaseSinkImpl for FileSink {
ref mut position,
} => (file, position),
State::Stopped => {
gst::element_error!(element, gst::CoreError::Failed, ["Not started yet"]);
gst::element_imp_error!(self, gst::CoreError::Failed, ["Not started yet"]);
return Err(gst::FlowError::Error);
}
};
gst::trace!(CAT, obj: element, "Rendering {:?}", buffer);
gst::trace!(CAT, imp: self, "Rendering {:?}", buffer);
let map = buffer.map_readable().map_err(|_| {
gst::element_error!(element, gst::CoreError::Failed, ["Failed to map buffer"]);
gst::element_imp_error!(self, gst::CoreError::Failed, ["Failed to map buffer"]);
gst::FlowError::Error
})?;
file.write_all(map.as_ref()).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Write,
["Failed to write buffer: {}", err]
);
@ -296,7 +282,7 @@ impl URIHandlerImpl for FileSink {
&["file"]
}
fn uri(&self, _element: &Self::Type) -> Option<String> {
fn uri(&self) -> Option<String> {
let settings = self.settings.lock().unwrap();
// Conversion to Url already checked while building the `FileLocation`
@ -307,13 +293,13 @@ impl URIHandlerImpl for FileSink {
})
}
fn set_uri(&self, element: &Self::Type, uri: &str) -> Result<(), glib::Error> {
fn set_uri(&self, uri: &str) -> Result<(), glib::Error> {
// Special case for "file://" as this is used by some applications to test
// with `gst_element_make_from_uri` if there's an element that supports the URI protocol
if uri != "file://" {
let file_location = FileLocation::try_from_uri_str(uri)?;
self.set_location(element, Some(file_location))
self.set_location(Some(file_location))
} else {
Ok(())
}

View file

@ -65,11 +65,7 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
impl FileSrc {
fn set_location(
&self,
element: &super::FileSrc,
location: Option<FileLocation>,
) -> Result<(), glib::Error> {
fn set_location(&self, location: Option<FileLocation>) -> Result<(), glib::Error> {
let state = self.state.lock().unwrap();
if let State::Started { .. } = *state {
return Err(glib::Error::new(
@ -99,20 +95,20 @@ impl FileSrc {
Some(ref location_cur) => {
gst::info!(
CAT,
obj: element,
imp: self,
"Changing `location` from {:?} to {}",
location_cur,
location,
);
}
None => {
gst::info!(CAT, obj: element, "Setting `location to {}", location,);
gst::info!(CAT, imp: self, "Setting `location to {}", location,);
}
}
Some(location)
}
None => {
gst::info!(CAT, obj: element, "Resetting `location` to None",);
gst::info!(CAT, imp: self, "Resetting `location` to None",);
None
}
};
@ -142,31 +138,25 @@ impl ObjectImpl for FileSrc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"location" => {
let res = match value.get::<Option<String>>() {
Ok(Some(location)) => FileLocation::try_from_path_str(location)
.and_then(|file_location| self.set_location(obj, Some(file_location))),
Ok(None) => self.set_location(obj, None),
.and_then(|file_location| self.set_location(Some(file_location))),
Ok(None) => self.set_location(None),
Err(_) => unreachable!("type checked upstream"),
};
if let Err(err) = res {
gst::error!(CAT, obj: obj, "Failed to set property `location`: {}", err);
gst::error!(CAT, imp: self, "Failed to set property `location`: {}", err);
}
}
_ => unimplemented!(),
};
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"location" => {
let settings = self.settings.lock().unwrap();
@ -181,10 +171,10 @@ impl ObjectImpl for FileSrc {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
obj.set_format(gst::Format::Bytes);
self.instance().set_format(gst::Format::Bytes);
}
}
@ -223,11 +213,11 @@ impl ElementImpl for FileSrc {
}
impl BaseSrcImpl for FileSrc {
fn is_seekable(&self, _src: &Self::Type) -> bool {
fn is_seekable(&self) -> bool {
true
}
fn size(&self, _src: &Self::Type) -> Option<u64> {
fn size(&self) -> Option<u64> {
let state = self.state.lock().unwrap();
if let State::Started { ref file, .. } = *state {
file.metadata().ok().map(|m| m.len())
@ -236,7 +226,7 @@ impl BaseSrcImpl for FileSrc {
}
}
fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
let mut state = self.state.lock().unwrap();
if let State::Started { .. } = *state {
unreachable!("FileSrc already started");
@ -261,16 +251,16 @@ impl BaseSrcImpl for FileSrc {
)
})?;
gst::debug!(CAT, obj: element, "Opened file {:?}", file);
gst::debug!(CAT, imp: self, "Opened file {:?}", file);
*state = State::Started { file, position: 0 };
gst::info!(CAT, obj: element, "Started");
gst::info!(CAT, imp: self, "Started");
Ok(())
}
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
let mut state = self.state.lock().unwrap();
if let State::Stopped = *state {
return Err(gst::error_msg!(
@ -281,14 +271,13 @@ impl BaseSrcImpl for FileSrc {
*state = State::Stopped;
gst::info!(CAT, obj: element, "Stopped");
gst::info!(CAT, imp: self, "Stopped");
Ok(())
}
fn fill(
&self,
element: &Self::Type,
offset: u64,
_length: u32,
buffer: &mut gst::BufferRef,
@ -301,15 +290,15 @@ impl BaseSrcImpl for FileSrc {
ref mut position,
} => (file, position),
State::Stopped => {
gst::element_error!(element, gst::CoreError::Failed, ["Not started yet"]);
gst::element_imp_error!(self, gst::CoreError::Failed, ["Not started yet"]);
return Err(gst::FlowError::Error);
}
};
if *position != offset {
file.seek(SeekFrom::Start(offset)).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::LibraryError::Failed,
["Failed to seek to {}: {}", offset, err.to_string()]
);
@ -321,13 +310,13 @@ impl BaseSrcImpl for FileSrc {
let size = {
let mut map = buffer.map_writable().map_err(|_| {
gst::element_error!(element, gst::LibraryError::Failed, ["Failed to map buffer"]);
gst::element_imp_error!(self, gst::LibraryError::Failed, ["Failed to map buffer"]);
gst::FlowError::Error
})?;
file.read(map.as_mut()).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::LibraryError::Failed,
["Failed to read at {}: {}", offset, err.to_string()]
);
@ -350,7 +339,7 @@ impl URIHandlerImpl for FileSrc {
&["file"]
}
fn uri(&self, _element: &Self::Type) -> Option<String> {
fn uri(&self) -> Option<String> {
let settings = self.settings.lock().unwrap();
// Conversion to Url already checked while building the `FileLocation`
@ -361,13 +350,13 @@ impl URIHandlerImpl for FileSrc {
})
}
fn set_uri(&self, element: &Self::Type, uri: &str) -> Result<(), glib::Error> {
fn set_uri(&self, uri: &str) -> Result<(), glib::Error> {
// Special case for "file://" as this is used by some applications to test
// with `gst_element_make_from_uri` if there's an element that supports the URI protocol
if uri != "file://" {
let file_location = FileLocation::try_from_uri_str(uri)?;
self.set_location(element, Some(file_location))
self.set_location(Some(file_location))
} else {
Ok(())
}

View file

@ -183,7 +183,6 @@ pub(crate) struct FMP4Mux {
impl FMP4Mux {
fn find_earliest_stream<'a>(
&self,
element: &super::FMP4Mux,
state: &'a mut State,
timeout: bool,
) -> Result<Option<(usize, &'a mut Stream)>, gst::FlowError> {
@ -255,21 +254,21 @@ impl FMP4Mux {
if !timeout && !all_have_data_or_eos {
gst::trace!(
CAT,
obj: element,
imp: self,
"No timeout and not all streams have a buffer or are EOS"
);
Ok(None)
} else if let Some((idx, stream, earliest_running_time)) = earliest_stream {
gst::trace!(
CAT,
obj: element,
imp: self,
"Stream {} is earliest stream with running time {}",
stream.sinkpad.name(),
earliest_running_time
);
Ok(Some((idx, stream)))
} else {
gst::trace!(CAT, obj: element, "No streams have data queued currently");
gst::trace!(CAT, imp: self, "No streams have data queued currently");
Ok(None)
}
}
@ -277,7 +276,6 @@ impl FMP4Mux {
// Queue incoming buffers as individual GOPs.
fn queue_gops(
&self,
element: &super::FMP4Mux,
_idx: usize,
stream: &mut Stream,
segment: &gst::FormattedSegment<gst::ClockTime>,
@ -439,7 +437,8 @@ impl FMP4Mux {
// If this is a multi-stream element then we need to update the PTS/DTS positions according
// to the output segment, specifically to re-timestamp them with the running time and
// adjust for the segment shift to compensate for negative DTS.
let class = element.class();
let aggregator = self.instance();
let class = aggregator.class();
let (pts_position, dts_position) = if class.as_ref().variant.is_single_stream() {
(pts_position, dts_position)
} else {
@ -609,7 +608,6 @@ impl FMP4Mux {
#[allow(clippy::type_complexity)]
fn drain_buffers(
&self,
element: &super::FMP4Mux,
state: &mut State,
settings: &Settings,
timeout: bool,
@ -652,7 +650,7 @@ impl FMP4Mux {
let fragment_start_pts = state.fragment_start_pts.unwrap();
gst::info!(
CAT,
obj: element,
imp: self,
"Starting to drain at {}",
fragment_start_pts
);
@ -898,7 +896,6 @@ impl FMP4Mux {
fn preprocess_drained_streams_onvif(
&self,
element: &super::FMP4Mux,
state: &mut State,
drained_streams: &mut [(
gst::Caps,
@ -906,7 +903,8 @@ impl FMP4Mux {
VecDeque<Buffer>,
)],
) -> Result<Option<gst::ClockTime>, gst::FlowError> {
if element.class().as_ref().variant != super::Variant::ONVIF {
let aggregator = self.instance();
if aggregator.class().as_ref().variant != super::Variant::ONVIF {
return Ok(None);
}
@ -1007,7 +1005,7 @@ impl FMP4Mux {
gst::debug!(
CAT,
obj: element,
imp: self,
"Configuring start UTC time {}",
start_utc_time.unwrap()
);
@ -1150,7 +1148,6 @@ impl FMP4Mux {
#[allow(clippy::type_complexity)]
fn interleave_buffers(
&self,
_element: &super::FMP4Mux,
settings: &Settings,
mut drained_streams: Vec<(
gst::Caps,
@ -1224,7 +1221,6 @@ impl FMP4Mux {
fn drain(
&self,
element: &super::FMP4Mux,
state: &mut State,
settings: &Settings,
timeout: bool,
@ -1232,9 +1228,9 @@ impl FMP4Mux {
upstream_events: &mut Vec<(gst_base::AggregatorPad, gst::Event)>,
) -> Result<(Option<gst::Caps>, Option<gst::BufferList>), gst::FlowError> {
if at_eos {
gst::info!(CAT, obj: element, "Draining at EOS");
gst::info!(CAT, imp: self, "Draining at EOS");
} else if timeout {
gst::info!(CAT, obj: element, "Draining at timeout");
gst::info!(CAT, imp: self, "Draining at timeout");
} else {
for stream in &state.streams {
if !stream.fragment_filled && !stream.sinkpad.is_eos() {
@ -1250,7 +1246,7 @@ impl FMP4Mux {
min_earliest_pts,
min_start_dts_position,
fragment_end_pts,
) = self.drain_buffers(element, state, settings, timeout, at_eos)?;
) = self.drain_buffers(state, settings, timeout, at_eos)?;
// Remove all GAP buffers before processing them further
for (_, _, buffers) in &mut drained_streams {
@ -1263,20 +1259,18 @@ impl FMP4Mux {
// For ONVIF, replace all timestamps with timestamps based on UTC times.
let max_end_utc_time =
self.preprocess_drained_streams_onvif(element, state, &mut drained_streams)?;
self.preprocess_drained_streams_onvif(state, &mut drained_streams)?;
// Create header now if it was not created before and return the caps
let mut caps = None;
if state.stream_header.is_none() {
let (_, new_caps) = self
.update_header(element, state, settings, false)?
.unwrap();
let (_, new_caps) = self.update_header(state, settings, false)?.unwrap();
caps = Some(new_caps);
}
// Interleave buffers according to the settings into a single vec
let (mut interleaved_buffers, streams) =
self.interleave_buffers(element, settings, drained_streams)?;
self.interleave_buffers(settings, drained_streams)?;
let mut buffer_list = None;
if interleaved_buffers.is_empty() {
@ -1316,7 +1310,7 @@ impl FMP4Mux {
state.sequence_number += 1;
let (mut fmp4_fragment_header, moof_offset) =
boxes::create_fmp4_fragment_header(super::FragmentHeaderConfiguration {
variant: element.class().as_ref().variant,
variant: self.instance().class().as_ref().variant,
sequence_number,
streams: streams.as_slice(),
buffers: interleaved_buffers.as_slice(),
@ -1324,7 +1318,7 @@ impl FMP4Mux {
.map_err(|err| {
gst::error!(
CAT,
obj: element,
imp: self,
"Failed to create FMP4 fragment header: {}",
err
);
@ -1394,7 +1388,7 @@ impl FMP4Mux {
// Update for the start PTS of the next fragment
gst::info!(
CAT,
obj: element,
imp: self,
"Starting new fragment at {}",
fragment_end_pts,
);
@ -1402,7 +1396,7 @@ impl FMP4Mux {
gst::debug!(
CAT,
obj: element,
imp: self,
"Sending force-keyunit events for running time {}",
fragment_end_pts + settings.fragment_duration,
);
@ -1435,7 +1429,7 @@ impl FMP4Mux {
buffer_list.as_mut().unwrap().get_mut().unwrap().add(mfra);
}
Err(err) => {
gst::error!(CAT, obj: element, "Failed to create mfra box: {}", err);
gst::error!(CAT, imp: self, "Failed to create mfra box: {}", err);
}
}
}
@ -1446,12 +1440,9 @@ impl FMP4Mux {
Ok((caps, buffer_list))
}
fn create_streams(
&self,
element: &super::FMP4Mux,
state: &mut State,
) -> Result<(), gst::FlowError> {
for pad in element
fn create_streams(&self, state: &mut State) -> Result<(), gst::FlowError> {
for pad in self
.instance()
.sink_pads()
.into_iter()
.map(|pad| pad.downcast::<gst_base::AggregatorPad>().unwrap())
@ -1511,7 +1502,7 @@ impl FMP4Mux {
}
if state.streams.is_empty() {
gst::error!(CAT, obj: element, "No streams available");
gst::error!(CAT, imp: self, "No streams available");
return Err(gst::FlowError::Error);
}
@ -1546,12 +1537,12 @@ impl FMP4Mux {
fn update_header(
&self,
element: &super::FMP4Mux,
state: &mut State,
settings: &Settings,
at_eos: bool,
) -> Result<Option<(gst::BufferList, gst::Caps)>, gst::FlowError> {
let class = element.class();
let aggregator = self.instance();
let class = aggregator.class();
let variant = class.as_ref().variant;
if settings.header_update_mode == super::HeaderUpdateMode::None && at_eos {
@ -1591,7 +1582,7 @@ impl FMP4Mux {
.map(|unix| unix.nseconds() / 100 + UNIX_1601_OFFSET * 10_000_000),
})
.map_err(|err| {
gst::error!(CAT, obj: element, "Failed to create FMP4 header: {}", err);
gst::error!(CAT, imp: self, "Failed to create FMP4 header: {}", err);
gst::FlowError::Error
})?;
@ -1680,13 +1671,7 @@ impl ObjectImpl for FMP4Mux {
&*PROPERTIES
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"fragment-duration" => {
let mut settings = self.settings.lock().unwrap();
@ -1694,7 +1679,7 @@ impl ObjectImpl for FMP4Mux {
if settings.fragment_duration != fragment_duration {
settings.fragment_duration = fragment_duration;
drop(settings);
obj.set_latency(fragment_duration, None);
self.instance().set_latency(fragment_duration, None);
}
}
@ -1733,7 +1718,7 @@ impl ObjectImpl for FMP4Mux {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"fragment-duration" => {
let settings = self.settings.lock().unwrap();
@ -1769,9 +1754,10 @@ impl ObjectImpl for FMP4Mux {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
let class = obj.class();
for templ in class.pad_template_list().filter(|templ| {
templ.presence() == gst::PadPresence::Always
@ -1794,7 +1780,6 @@ impl GstObjectImpl for FMP4Mux {}
impl ElementImpl for FMP4Mux {
fn request_new_pad(
&self,
element: &Self::Type,
templ: &gst::PadTemplate,
name: Option<String>,
caps: Option<&gst::Caps>,
@ -1803,25 +1788,24 @@ impl ElementImpl for FMP4Mux {
if state.stream_header.is_some() {
gst::error!(
CAT,
obj: element,
imp: self,
"Can't request new pads after header was generated"
);
return None;
}
self.parent_request_new_pad(element, templ, name, caps)
self.parent_request_new_pad(templ, name, caps)
}
}
impl AggregatorImpl for FMP4Mux {
fn next_time(&self, _aggregator: &Self::Type) -> Option<gst::ClockTime> {
fn next_time(&self) -> Option<gst::ClockTime> {
let state = self.state.lock().unwrap();
state.fragment_start_pts.opt_add(state.timeout_delay)
}
fn sink_query(
&self,
aggregator: &Self::Type,
aggregator_pad: &gst_base::AggregatorPad,
query: &mut gst::QueryRef,
) -> bool {
@ -1845,13 +1829,12 @@ impl AggregatorImpl for FMP4Mux {
true
}
_ => self.parent_sink_query(aggregator, aggregator_pad, query),
_ => self.parent_sink_query(aggregator_pad, query),
}
}
fn sink_event_pre_queue(
&self,
aggregator: &Self::Type,
aggregator_pad: &gst_base::AggregatorPad,
mut event: gst::Event,
) -> Result<gst::FlowSuccess, gst::FlowError> {
@ -1872,18 +1855,13 @@ impl AggregatorImpl for FMP4Mux {
.seqnum(event.seqnum())
.build();
}
self.parent_sink_event_pre_queue(aggregator, aggregator_pad, event)
self.parent_sink_event_pre_queue(aggregator_pad, event)
}
_ => self.parent_sink_event_pre_queue(aggregator, aggregator_pad, event),
_ => self.parent_sink_event_pre_queue(aggregator_pad, event),
}
}
fn sink_event(
&self,
aggregator: &Self::Type,
aggregator_pad: &gst_base::AggregatorPad,
event: gst::Event,
) -> bool {
fn sink_event(&self, aggregator_pad: &gst_base::AggregatorPad, event: gst::Event) -> bool {
use gst::EventView;
gst::trace!(CAT, obj: aggregator_pad, "Handling event {:?}", event);
@ -1901,26 +1879,27 @@ impl AggregatorImpl for FMP4Mux {
// Only forward the segment event verbatim if this is a single stream variant.
// Otherwise we have to produce a default segment and re-timestamp all buffers
// with their running time.
let aggregator = self.instance();
let class = aggregator.class();
if class.as_ref().variant.is_single_stream() {
aggregator.update_segment(&segment);
}
self.parent_sink_event(aggregator, aggregator_pad, event)
self.parent_sink_event(aggregator_pad, event)
}
EventView::Tag(_ev) => {
// TODO: Maybe store for putting into the headers of the next fragment?
self.parent_sink_event(aggregator, aggregator_pad, event)
self.parent_sink_event(aggregator_pad, event)
}
_ => self.parent_sink_event(aggregator, aggregator_pad, event),
_ => self.parent_sink_event(aggregator_pad, event),
}
}
fn src_query(&self, aggregator: &Self::Type, query: &mut gst::QueryRef) -> bool {
fn src_query(&self, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::trace!(CAT, obj: aggregator, "Handling query {:?}", query);
gst::trace!(CAT, imp: self, "Handling query {:?}", query);
match query.view_mut() {
QueryViewMut::Seeking(q) => {
@ -1928,23 +1907,23 @@ impl AggregatorImpl for FMP4Mux {
q.set(false, gst::ClockTime::ZERO, gst::ClockTime::NONE);
true
}
_ => self.parent_src_query(aggregator, query),
_ => self.parent_src_query(query),
}
}
fn src_event(&self, aggregator: &Self::Type, event: gst::Event) -> bool {
fn src_event(&self, event: gst::Event) -> bool {
use gst::EventView;
gst::trace!(CAT, obj: aggregator, "Handling event {:?}", event);
gst::trace!(CAT, imp: self, "Handling event {:?}", event);
match event.view() {
EventView::Seek(_ev) => false,
_ => self.parent_src_event(aggregator, event),
_ => self.parent_src_event(event),
}
}
fn flush(&self, aggregator: &Self::Type) -> Result<gst::FlowSuccess, gst::FlowError> {
self.parent_flush(aggregator)?;
fn flush(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
self.parent_flush()?;
let mut state = self.state.lock().unwrap();
@ -1962,23 +1941,24 @@ impl AggregatorImpl for FMP4Mux {
Ok(gst::FlowSuccess::Ok)
}
fn stop(&self, aggregator: &Self::Type) -> Result<(), gst::ErrorMessage> {
gst::trace!(CAT, obj: aggregator, "Stopping");
fn stop(&self) -> Result<(), gst::ErrorMessage> {
gst::trace!(CAT, imp: self, "Stopping");
let _ = self.parent_stop(aggregator);
let _ = self.parent_stop();
*self.state.lock().unwrap() = State::default();
Ok(())
}
fn start(&self, aggregator: &Self::Type) -> Result<(), gst::ErrorMessage> {
gst::trace!(CAT, obj: aggregator, "Starting");
fn start(&self) -> Result<(), gst::ErrorMessage> {
gst::trace!(CAT, imp: self, "Starting");
self.parent_start(aggregator)?;
self.parent_start()?;
// For non-single-stream variants configure a default segment that allows for negative
// DTS so that we can correctly re-timestamp buffers with their running times.
let aggregator = self.instance();
let class = aggregator.class();
if !class.as_ref().variant.is_single_stream() {
let mut segment = gst::FormattedSegment::<gst::ClockTime>::new();
@ -1992,15 +1972,11 @@ impl AggregatorImpl for FMP4Mux {
Ok(())
}
fn negotiate(&self, _aggregator: &Self::Type) -> bool {
fn negotiate(&self) -> bool {
true
}
fn aggregate(
&self,
aggregator: &Self::Type,
timeout: bool,
) -> Result<gst::FlowSuccess, gst::FlowError> {
fn aggregate(&self, timeout: bool) -> Result<gst::FlowSuccess, gst::FlowError> {
let settings = self.settings.lock().unwrap().clone();
let mut upstream_events = vec![];
@ -2011,7 +1987,7 @@ impl AggregatorImpl for FMP4Mux {
// Create streams
if state.streams.is_empty() {
self.create_streams(aggregator, &mut state)?;
self.create_streams(&mut state)?;
}
// Queue buffers from all streams that are not filled for the current fragment yet
@ -2020,9 +1996,7 @@ impl AggregatorImpl for FMP4Mux {
// fill-level at all sinkpads in sync.
let fragment_start_pts = state.fragment_start_pts;
while let Some((idx, stream)) =
self.find_earliest_stream(aggregator, &mut state, timeout)?
{
while let Some((idx, stream)) = self.find_earliest_stream(&mut state, timeout)? {
// Can only happen if the stream was flushed in the meantime
let buffer = match stream.sinkpad.pop_buffer() {
Some(buffer) => buffer,
@ -2045,7 +2019,7 @@ impl AggregatorImpl for FMP4Mux {
};
// Queue up the buffer and update GOP tracking state
self.queue_gops(aggregator, idx, stream, &segment, buffer)?;
self.queue_gops(idx, stream, &segment, buffer)?;
// Check if this stream is filled enough now.
if let Some((queued_end_pts, fragment_start_pts)) = Option::zip(
@ -2091,13 +2065,13 @@ impl AggregatorImpl for FMP4Mux {
}
if let Some(earliest_pts) = earliest_pts {
gst::info!(CAT, obj: aggregator, "Got earliest PTS {}", earliest_pts);
gst::info!(CAT, imp: self, "Got earliest PTS {}", earliest_pts);
state.earliest_pts = Some(earliest_pts);
state.fragment_start_pts = Some(earliest_pts);
gst::debug!(
CAT,
obj: aggregator,
imp: self,
"Sending first force-keyunit event for running time {}",
earliest_pts + settings.fragment_duration,
);
@ -2130,12 +2104,11 @@ impl AggregatorImpl for FMP4Mux {
all_eos = state.streams.iter().all(|stream| stream.sinkpad.is_eos());
if all_eos {
gst::debug!(CAT, obj: aggregator, "All streams are EOS now");
gst::debug!(CAT, imp: self, "All streams are EOS now");
}
// If enough GOPs were queued, drain and create the output fragment
match self.drain(
aggregator,
&mut state,
&settings,
timeout,
@ -2144,8 +2117,8 @@ impl AggregatorImpl for FMP4Mux {
) {
Ok(res) => res,
Err(gst_base::AGGREGATOR_FLOW_NEED_DATA) => {
gst::element_warning!(
aggregator,
gst::element_imp_warning!(
self,
gst::StreamError::Format,
["Longer GOPs than fragment duration"]
);
@ -2166,38 +2139,30 @@ impl AggregatorImpl for FMP4Mux {
}
if let Some(caps) = caps {
gst::debug!(
CAT,
obj: aggregator,
"Setting caps on source pad: {:?}",
caps
);
aggregator.set_src_caps(&caps);
gst::debug!(CAT, imp: self, "Setting caps on source pad: {:?}", caps);
self.instance().set_src_caps(&caps);
}
if let Some(buffers) = buffers {
gst::trace!(CAT, obj: aggregator, "Pushing buffer list {:?}", buffers);
aggregator.finish_buffer_list(buffers)?;
gst::trace!(CAT, imp: self, "Pushing buffer list {:?}", buffers);
self.instance().finish_buffer_list(buffers)?;
}
if all_eos {
gst::debug!(CAT, obj: aggregator, "Doing EOS handling");
gst::debug!(CAT, imp: self, "Doing EOS handling");
if settings.header_update_mode != super::HeaderUpdateMode::None {
let updated_header = self.update_header(
aggregator,
&mut self.state.lock().unwrap(),
&settings,
true,
);
let updated_header =
self.update_header(&mut self.state.lock().unwrap(), &settings, true);
match updated_header {
Ok(Some((buffer_list, caps))) => {
match settings.header_update_mode {
super::HeaderUpdateMode::None => unreachable!(),
super::HeaderUpdateMode::Rewrite => {
let src_pad = aggregator.src_pad();
let mut q = gst::query::Seeking::new(gst::Format::Bytes);
if src_pad.peer_query(&mut q) && q.result().0 {
if self.instance().src_pad().peer_query(&mut q) && q.result().0 {
let aggregator = self.instance();
aggregator.set_src_caps(&caps);
// Seek to the beginning with a default bytes segment
@ -2209,7 +2174,7 @@ impl AggregatorImpl for FMP4Mux {
if let Err(err) = aggregator.finish_buffer_list(buffer_list) {
gst::error!(
CAT,
obj: aggregator,
imp: self,
"Failed pushing updated header buffer downstream: {:?}",
err,
);
@ -2217,17 +2182,19 @@ impl AggregatorImpl for FMP4Mux {
} else {
gst::error!(
CAT,
obj: aggregator,
imp: self,
"Can't rewrite header because downstream is not seekable"
);
}
}
super::HeaderUpdateMode::Update => {
let aggregator = self.instance();
aggregator.set_src_caps(&caps);
if let Err(err) = aggregator.finish_buffer_list(buffer_list) {
gst::error!(
CAT,
obj: aggregator,
imp: self,
"Failed pushing updated header buffer downstream: {:?}",
err,
);
@ -2239,7 +2206,7 @@ impl AggregatorImpl for FMP4Mux {
Err(err) => {
gst::error!(
CAT,
obj: aggregator,
imp: self,
"Failed to generate updated header: {:?}",
err
);

View file

@ -99,14 +99,14 @@ impl State {
// retrieval
fn decrypt_into_adapter(
&mut self,
element: &super::Decrypter,
imp: &Decrypter,
pad: &gst::Pad,
buffer: &gst::Buffer,
chunk_index: u64,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let map = buffer.map_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
imp,
gst::StreamError::Format,
["Failed to map buffer readable"]
);
@ -122,8 +122,8 @@ impl State {
for subbuffer in map.chunks(block_size) {
let plain =
box_::open_precomputed(subbuffer, &nonce, &self.precomputed_key).map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
imp,
gst::StreamError::Format,
["Failed to decrypt buffer"]
);
@ -255,7 +255,6 @@ impl Decrypter {
fn src_activatemode_function(
&self,
_pad: &gst::Pad,
element: &super::Decrypter,
mode: gst::PadMode,
active: bool,
) -> Result<(), gst::LoggableError> {
@ -267,7 +266,7 @@ impl Decrypter {
// Set the nonce and block size from the headers
// right after we activate the pad
self.check_headers(element)
self.check_headers()
}
gst::PadMode::Push => Err(gst::loggable_error!(CAT, "Push mode not supported")),
_ => Err(gst::loggable_error!(
@ -278,12 +277,7 @@ impl Decrypter {
}
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::Decrypter,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
@ -306,7 +300,7 @@ impl Decrypter {
}
QueryViewMut::Duration(q) => {
if q.format() != gst::Format::Bytes {
return pad.query_default(Some(element), query);
return pad.query_default(Some(&*self.instance()), query);
}
/* First let's query the bytes duration upstream */
@ -348,11 +342,11 @@ impl Decrypter {
true
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
fn check_headers(&self, element: &super::Decrypter) -> Result<(), gst::LoggableError> {
fn check_headers(&self) -> Result<(), gst::LoggableError> {
let is_none = {
let mutex_state = self.state.lock().unwrap();
let state = mutex_state.as_ref().unwrap();
@ -372,26 +366,22 @@ impl Decrypter {
"Failed to pull nonce from the stream, reason: {:?}",
err
);
err.log_with_object(element);
err
})?;
if buffer.size() != crate::HEADERS_SIZE {
let err = gst::loggable_error!(CAT, "Headers buffer has wrong size");
err.log_with_object(element);
return Err(err);
}
let map = buffer.map_readable().map_err(|_| {
let err = gst::loggable_error!(CAT, "Failed to map buffer readable");
err.log_with_object(element);
err
})?;
let sodium_header_slice = &map[..crate::TYPEFIND_HEADER_SIZE];
if sodium_header_slice != crate::TYPEFIND_HEADER {
let err = gst::loggable_error!(CAT, "Buffer has wrong typefind header");
err.log_with_object(element);
return Err(err);
}
@ -400,7 +390,6 @@ impl Decrypter {
assert_eq!(nonce_slice.len(), box_::NONCEBYTES);
let nonce = box_::Nonce::from_slice(nonce_slice).ok_or_else(|| {
let err = gst::loggable_error!(CAT, "Failed to create nonce from buffer");
err.log_with_object(&self.srcpad);
err
})?;
@ -416,9 +405,9 @@ impl Decrypter {
let state = state.as_mut().unwrap();
state.initial_nonce = Some(nonce);
gst::debug!(CAT, obj: element, "Setting nonce to: {:?}", nonce.0);
gst::debug!(CAT, imp: self, "Setting nonce to: {:?}", nonce.0);
state.block_size = Some(block_size);
gst::debug!(CAT, obj: element, "Setting block size to: {}", block_size);
gst::debug!(CAT, imp: self, "Setting block size to: {}", block_size);
Ok(())
}
@ -426,7 +415,6 @@ impl Decrypter {
fn pull_requested_buffer(
&self,
pad: &gst::Pad,
element: &super::Decrypter,
requested_size: u32,
block_size: u32,
chunk_index: u64,
@ -441,8 +429,8 @@ impl Decrypter {
// calculate how many chunks are needed, if we need something like 3.2
// round the number to 4 and cut the buffer afterwards.
let checked = requested_size.checked_add(block_size).ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::LibraryError::Failed,
[
"Addition overflow when adding requested pull size and block size: {} + {}",
@ -459,8 +447,8 @@ impl Decrypter {
// Pull a buffer of all the chunks we will need
let checked_size = total_chunks.checked_mul(block_size).ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::LibraryError::Failed,
[
"Overflowed trying to calculate the buffer size to pull: {} * {}",
@ -494,7 +482,6 @@ impl Decrypter {
fn range(
&self,
pad: &gst::Pad,
element: &super::Decrypter,
offset: u64,
buffer: Option<&mut gst::BufferRef>,
requested_size: u32,
@ -519,20 +506,15 @@ impl Decrypter {
assert!(pull_offset <= std::u32::MAX as u64);
let pull_offset = pull_offset as u32;
let pulled_buffer = self.pull_requested_buffer(
pad,
element,
requested_size + pull_offset,
block_size,
chunk_index,
)?;
let pulled_buffer =
self.pull_requested_buffer(pad, requested_size + pull_offset, block_size, chunk_index)?;
let mut state = self.state.lock().unwrap();
// This will only be run after READY state,
// and will be guaranted to be initialized
let state = state.as_mut().unwrap();
state.decrypt_into_adapter(element, &self.srcpad, &pulled_buffer, chunk_index)?;
state.decrypt_into_adapter(self, &self.srcpad, &pulled_buffer, chunk_index)?;
let adapter_offset = pull_offset as usize;
state.requested_buffer(&self.srcpad, buffer, requested_size, adapter_offset)
@ -555,7 +537,7 @@ impl ObjectSubclass for Decrypter {
Decrypter::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|decrypter, element| decrypter.range(pad, element, offset, buffer, size),
|decrypter| decrypter.range(pad, offset, buffer, size),
)
})
.activatemode_function(|pad, parent, mode, active| {
@ -567,16 +549,14 @@ impl ObjectSubclass for Decrypter {
"Panic activating srcpad with mode"
))
},
|decrypter, element| {
decrypter.src_activatemode_function(pad, element, mode, active)
},
|decrypter| decrypter.src_activatemode_function(pad, mode, active),
)
})
.query_function(|pad, parent, query| {
Decrypter::catch_panic_pad_function(
parent,
|| false,
|decrypter, element| decrypter.src_query(pad, element, query),
|decrypter| decrypter.src_query(pad, query),
)
})
.build();
@ -612,20 +592,15 @@ impl ObjectImpl for Decrypter {
PROPERTIES.as_ref()
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"sender-key" => {
let mut props = self.props.lock().unwrap();
@ -641,7 +616,7 @@ impl ObjectImpl for Decrypter {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"receiver-key" => {
let props = self.props.lock().unwrap();
@ -696,10 +671,9 @@ impl ElementImpl for Decrypter {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::debug!(CAT, obj: element, "Changing state {:?}", transition);
gst::debug!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
@ -708,7 +682,7 @@ impl ElementImpl for Decrypter {
// Create an internal state struct from the provided properties or
// refuse to change state
let state_ = State::from_props(&props).map_err(|err| {
element.post_error_message(err);
self.post_error_message(err);
gst::StateChangeError
})?;
@ -721,7 +695,7 @@ impl ElementImpl for Decrypter {
_ => (),
}
let success = self.parent_change_state(element, transition)?;
let success = self.parent_change_state(transition)?;
if transition == gst::StateChange::ReadyToNull {
let _ = self.state.lock().unwrap().take();

View file

@ -166,7 +166,6 @@ impl Encrypter {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::Encrypter,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@ -196,7 +195,7 @@ impl Encrypter {
for buffer in buffers {
self.srcpad.push(buffer).map_err(|err| {
gst::error!(CAT, obj: element, "Failed to push buffer {:?}", err);
gst::error!(CAT, imp: self, "Failed to push buffer {:?}", err);
err
})?;
}
@ -204,7 +203,7 @@ impl Encrypter {
Ok(gst::FlowSuccess::Ok)
}
fn sink_event(&self, pad: &gst::Pad, element: &super::Encrypter, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -239,34 +238,29 @@ impl Encrypter {
for buffer in buffers {
if let Err(err) = self.srcpad.push(buffer) {
gst::error!(CAT, obj: element, "Failed to push buffer at EOS {:?}", err);
gst::error!(CAT, imp: self, "Failed to push buffer at EOS {:?}", err);
return false;
}
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_event(&self, pad: &gst::Pad, element: &super::Encrypter, event: gst::Event) -> bool {
fn src_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() {
EventView::Seek(_) => false,
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::Encrypter,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
@ -284,7 +278,7 @@ impl Encrypter {
}
QueryViewMut::Duration(q) => {
if q.format() != gst::Format::Bytes {
return pad.query_default(Some(element), query);
return pad.query_default(Some(&*self.instance()), query);
}
/* First let's query the bytes duration upstream */
@ -325,7 +319,7 @@ impl Encrypter {
true
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
}
@ -343,14 +337,14 @@ impl ObjectSubclass for Encrypter {
Encrypter::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|encrypter, element| encrypter.sink_chain(pad, element, buffer),
|encrypter| encrypter.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
Encrypter::catch_panic_pad_function(
parent,
|| false,
|encrypter, element| encrypter.sink_event(pad, element, event),
|encrypter| encrypter.sink_event(pad, event),
)
})
.build();
@ -361,14 +355,14 @@ impl ObjectSubclass for Encrypter {
Encrypter::catch_panic_pad_function(
parent,
|| false,
|encrypter, element| encrypter.src_query(pad, element, query),
|encrypter| encrypter.src_query(pad, query),
)
})
.event_function(|pad, parent, event| {
Encrypter::catch_panic_pad_function(
parent,
|| false,
|encrypter, element| encrypter.src_event(pad, element, event),
|encrypter| encrypter.src_event(pad, event),
)
})
.build();
@ -410,20 +404,15 @@ impl ObjectImpl for Encrypter {
PROPERTIES.as_ref()
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"sender-key" => {
let mut props = self.props.lock().unwrap();
@ -444,7 +433,7 @@ impl ObjectImpl for Encrypter {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"receiver-key" => {
let props = self.props.lock().unwrap();
@ -504,10 +493,9 @@ impl ElementImpl for Encrypter {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::debug!(CAT, obj: element, "Changing state {:?}", transition);
gst::debug!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
@ -516,7 +504,7 @@ impl ElementImpl for Encrypter {
// Create an internal state struct from the provided properties or
// refuse to change state
let state_ = State::from_props(&props).map_err(|err| {
element.post_error_message(err);
self.post_error_message(err);
gst::StateChangeError
})?;
@ -529,7 +517,7 @@ impl ElementImpl for Encrypter {
_ => (),
}
let success = self.parent_change_state(element, transition)?;
let success = self.parent_change_state(transition)?;
if transition == gst::StateChange::ReadyToNull {
let _ = self.state.lock().unwrap().take();

View file

@ -608,12 +608,12 @@ impl TestSink {
self.item_sender.lock().unwrap().as_ref().unwrap().clone()
}
fn prepare(&self, element: &super::TestSink) -> Result<(), gst::ErrorMessage> {
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
let raise_log_level = self.settings.lock().unwrap().raise_log_level;
if raise_log_level {
gst::debug!(CAT, obj: element, "Preparing");
gst::debug!(CAT, imp: self, "Preparing");
} else {
gst::trace!(CAT, obj: element, "Preparing");
gst::trace!(CAT, imp: self, "Preparing");
}
let context = {
@ -629,70 +629,70 @@ impl TestSink {
// Enable backpressure for items
let (item_sender, item_receiver) = flume::bounded(0);
let task_impl = TestSinkTask::new(element, item_receiver);
let task_impl = TestSinkTask::new(&*self.instance(), item_receiver);
self.task.prepare(task_impl, context).block_on()?;
*self.item_sender.lock().unwrap() = Some(item_sender);
if raise_log_level {
gst::debug!(CAT, obj: element, "Prepared");
gst::debug!(CAT, imp: self, "Prepared");
} else {
gst::trace!(CAT, obj: element, "Prepared");
gst::trace!(CAT, imp: self, "Prepared");
}
Ok(())
}
fn unprepare(&self, element: &super::TestSink) {
fn unprepare(&self) {
let raise_log_level = self.settings.lock().unwrap().raise_log_level;
if raise_log_level {
gst::debug!(CAT, obj: element, "Unpreparing");
gst::debug!(CAT, imp: self, "Unpreparing");
} else {
gst::trace!(CAT, obj: element, "Unpreparing");
gst::trace!(CAT, imp: self, "Unpreparing");
}
self.task.unprepare().block_on().unwrap();
if raise_log_level {
gst::debug!(CAT, obj: element, "Unprepared");
gst::debug!(CAT, imp: self, "Unprepared");
} else {
gst::trace!(CAT, obj: element, "Unprepared");
gst::trace!(CAT, imp: self, "Unprepared");
}
}
fn stop(&self, element: &super::TestSink) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
let raise_log_level = self.settings.lock().unwrap().raise_log_level;
if raise_log_level {
gst::debug!(CAT, obj: element, "Stopping");
gst::debug!(CAT, imp: self, "Stopping");
} else {
gst::trace!(CAT, obj: element, "Stopping");
gst::trace!(CAT, imp: self, "Stopping");
}
self.task.stop().block_on()?;
if raise_log_level {
gst::debug!(CAT, obj: element, "Stopped");
gst::debug!(CAT, imp: self, "Stopped");
} else {
gst::trace!(CAT, obj: element, "Stopped");
gst::trace!(CAT, imp: self, "Stopped");
}
Ok(())
}
fn start(&self, element: &super::TestSink) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
let raise_log_level = self.settings.lock().unwrap().raise_log_level;
if raise_log_level {
gst::debug!(CAT, obj: element, "Starting");
gst::debug!(CAT, imp: self, "Starting");
} else {
gst::trace!(CAT, obj: element, "Starting");
gst::trace!(CAT, imp: self, "Starting");
}
self.task.start().block_on()?;
if raise_log_level {
gst::debug!(CAT, obj: element, "Started");
gst::debug!(CAT, imp: self, "Started");
} else {
gst::trace!(CAT, obj: element, "Started");
gst::trace!(CAT, imp: self, "Started");
}
Ok(())
@ -760,13 +760,7 @@ impl ObjectImpl for TestSink {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"context" => {
@ -800,7 +794,7 @@ impl ObjectImpl for TestSink {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"context" => settings.context.to_value(),
@ -816,12 +810,12 @@ impl ObjectImpl for TestSink {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.sink_pad.gst_pad()).unwrap();
gstthreadshare::set_element_flags(obj, gst::ElementFlags::SINK);
obj.set_element_flags(gst::ElementFlags::SINK);
}
}
@ -861,30 +855,29 @@ impl ElementImpl for TestSink {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare(element).map_err(|err| {
element.post_error_message(err);
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::ReadyToPaused => {
self.start(element).map_err(|_| gst::StateChangeError)?;
self.start().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::PausedToReady => {
self.stop(element).map_err(|_| gst::StateChangeError)?;
self.stop().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::ReadyToNull => {
self.unprepare(element);
self.unprepare();
}
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -318,12 +318,12 @@ pub struct TestSrc {
}
impl TestSrc {
fn prepare(&self, element: &super::TestSrc) -> Result<(), gst::ErrorMessage> {
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
let raise_log_level = self.settings.lock().unwrap().raise_log_level;
if raise_log_level {
gst::debug!(CAT, obj: element, "Preparing");
gst::debug!(CAT, imp: self, "Preparing");
} else {
gst::trace!(CAT, obj: element, "Preparing");
gst::trace!(CAT, imp: self, "Preparing");
}
let settings = self.settings.lock().unwrap();
@ -337,87 +337,87 @@ impl TestSrc {
drop(settings);
self.task
.prepare(SrcTask::new(element.clone()), context)
.prepare(SrcTask::new(self.instance().clone()), context)
.block_on()?;
if raise_log_level {
gst::debug!(CAT, obj: element, "Prepared");
gst::debug!(CAT, imp: self, "Prepared");
} else {
gst::trace!(CAT, obj: element, "Prepared");
gst::trace!(CAT, imp: self, "Prepared");
}
Ok(())
}
fn unprepare(&self, element: &super::TestSrc) {
fn unprepare(&self) {
let raise_log_level = self.settings.lock().unwrap().raise_log_level;
if raise_log_level {
gst::debug!(CAT, obj: element, "Unpreparing");
gst::debug!(CAT, imp: self, "Unpreparing");
} else {
gst::trace!(CAT, obj: element, "Unpreparing");
gst::trace!(CAT, imp: self, "Unpreparing");
}
self.task.unprepare().block_on().unwrap();
if raise_log_level {
gst::debug!(CAT, obj: element, "Unprepared");
gst::debug!(CAT, imp: self, "Unprepared");
} else {
gst::trace!(CAT, obj: element, "Unprepared");
gst::trace!(CAT, imp: self, "Unprepared");
}
}
fn stop(&self, element: &super::TestSrc) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
let raise_log_level = self.settings.lock().unwrap().raise_log_level;
if raise_log_level {
gst::debug!(CAT, obj: element, "Stopping");
gst::debug!(CAT, imp: self, "Stopping");
} else {
gst::trace!(CAT, obj: element, "Stopping");
gst::trace!(CAT, imp: self, "Stopping");
}
self.task.stop().block_on()?;
if raise_log_level {
gst::debug!(CAT, obj: element, "Stopped");
gst::debug!(CAT, imp: self, "Stopped");
} else {
gst::trace!(CAT, obj: element, "Stopped");
gst::trace!(CAT, imp: self, "Stopped");
}
Ok(())
}
fn start(&self, element: &super::TestSrc) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
let raise_log_level = self.settings.lock().unwrap().raise_log_level;
if raise_log_level {
gst::debug!(CAT, obj: element, "Starting");
gst::debug!(CAT, imp: self, "Starting");
} else {
gst::trace!(CAT, obj: element, "Starting");
gst::trace!(CAT, imp: self, "Starting");
}
self.task.start().block_on()?;
if raise_log_level {
gst::debug!(CAT, obj: element, "Started");
gst::debug!(CAT, imp: self, "Started");
} else {
gst::trace!(CAT, obj: element, "Started");
gst::trace!(CAT, imp: self, "Started");
}
Ok(())
}
fn pause(&self, element: &super::TestSrc) -> Result<(), gst::ErrorMessage> {
fn pause(&self) -> Result<(), gst::ErrorMessage> {
let raise_log_level = self.settings.lock().unwrap().raise_log_level;
if raise_log_level {
gst::debug!(CAT, obj: element, "Pausing");
gst::debug!(CAT, imp: self, "Pausing");
} else {
gst::trace!(CAT, obj: element, "Pausing");
gst::trace!(CAT, imp: self, "Pausing");
}
self.task.pause().block_on()?;
if raise_log_level {
gst::debug!(CAT, obj: element, "Paused");
gst::debug!(CAT, imp: self, "Paused");
} else {
gst::trace!(CAT, obj: element, "Paused");
gst::trace!(CAT, imp: self, "Paused");
}
Ok(())
@ -479,13 +479,7 @@ impl ObjectImpl for TestSrc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"context" => {
@ -515,7 +509,7 @@ impl ObjectImpl for TestSrc {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"context" => settings.context.to_value(),
@ -531,12 +525,12 @@ impl ObjectImpl for TestSrc {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.src_pad.gst_pad()).unwrap();
gstthreadshare::set_element_flags(obj, gst::ElementFlags::SOURCE);
obj.set_element_flags(gst::ElementFlags::SOURCE);
}
}
@ -575,41 +569,40 @@ impl ElementImpl for TestSrc {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare(element).map_err(|err| {
element.post_error_message(err);
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::PlayingToPaused => {
self.pause(element).map_err(|_| gst::StateChangeError)?;
self.pause().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::ReadyToNull => {
self.unprepare(element);
self.unprepare();
}
_ => (),
}
let mut success = self.parent_change_state(element, transition)?;
let mut success = self.parent_change_state(transition)?;
match transition {
gst::StateChange::ReadyToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
}
gst::StateChange::PausedToPlaying => {
self.start(element).map_err(|_| gst::StateChangeError)?;
self.start().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::PlayingToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
}
gst::StateChange::PausedToReady => {
self.stop(element).map_err(|_| gst::StateChangeError)?;
self.stop().map_err(|_| gst::StateChangeError)?;
}
_ => (),
}

View file

@ -319,24 +319,24 @@ pub struct AppSrc {
}
impl AppSrc {
fn push_buffer(&self, element: &super::AppSrc, mut buffer: gst::Buffer) -> bool {
fn push_buffer(&self, mut buffer: gst::Buffer) -> bool {
let state = self.task.lock_state();
if *state != TaskState::Started && *state != TaskState::Paused {
gst::debug!(CAT, obj: element, "Rejecting buffer due to element state");
gst::debug!(CAT, imp: self, "Rejecting buffer due to element state");
return false;
}
let do_timestamp = self.settings.lock().unwrap().do_timestamp;
if do_timestamp {
if let Some(clock) = element.clock() {
let base_time = element.base_time();
if let Some(clock) = self.instance().clock() {
let base_time = self.instance().base_time();
let now = clock.time();
let buffer = buffer.make_mut();
buffer.set_dts(now.opt_checked_sub(base_time).ok().flatten());
buffer.set_pts(None);
} else {
gst::error!(CAT, obj: element, "Don't have a clock yet");
gst::error!(CAT, imp: self, "Don't have a clock yet");
return false;
}
}
@ -349,13 +349,13 @@ impl AppSrc {
{
Ok(_) => true,
Err(err) => {
gst::error!(CAT, obj: element, "Failed to queue buffer: {}", err);
gst::error!(CAT, imp: self, "Failed to queue buffer: {}", err);
false
}
}
}
fn end_of_stream(&self, element: &super::AppSrc) -> bool {
fn end_of_stream(&self) -> bool {
let mut sender = self.sender.lock().unwrap();
let sender = match sender.as_mut() {
Some(sender) => sender,
@ -365,14 +365,14 @@ impl AppSrc {
match sender.try_send(StreamItem::Event(gst::event::Eos::new())) {
Ok(_) => true,
Err(err) => {
gst::error!(CAT, obj: element, "Failed to queue EOS: {}", err);
gst::error!(CAT, imp: self, "Failed to queue EOS: {}", err);
false
}
}
}
fn prepare(&self, element: &super::AppSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Preparing");
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Preparing");
let settings = self.settings.lock().unwrap();
let context =
@ -396,41 +396,41 @@ impl AppSrc {
*self.sender.lock().unwrap() = Some(sender);
self.task
.prepare(AppSrcTask::new(element.clone(), receiver), context)
.prepare(AppSrcTask::new(self.instance().clone(), receiver), context)
.block_on()?;
gst::debug!(CAT, obj: element, "Prepared");
gst::debug!(CAT, imp: self, "Prepared");
Ok(())
}
fn unprepare(&self, element: &super::AppSrc) {
gst::debug!(CAT, obj: element, "Unpreparing");
fn unprepare(&self) {
gst::debug!(CAT, imp: self, "Unpreparing");
*self.sender.lock().unwrap() = None;
self.task.unprepare().block_on().unwrap();
gst::debug!(CAT, obj: element, "Unprepared");
gst::debug!(CAT, imp: self, "Unprepared");
}
fn stop(&self, element: &super::AppSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Stopping");
fn stop(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Stopping");
self.task.stop().block_on()?;
gst::debug!(CAT, obj: element, "Stopped");
gst::debug!(CAT, imp: self, "Stopped");
Ok(())
}
fn start(&self, element: &super::AppSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Starting");
fn start(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Starting");
self.task.start().block_on()?;
gst::debug!(CAT, obj: element, "Started");
gst::debug!(CAT, imp: self, "Started");
Ok(())
}
fn pause(&self, element: &super::AppSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Pausing");
fn pause(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Pausing");
self.task.pause().block_on()?;
gst::debug!(CAT, obj: element, "Paused");
gst::debug!(CAT, imp: self, "Paused");
Ok(())
}
}
@ -503,7 +503,7 @@ impl ObjectImpl for AppSrc {
let buffer = args[1].get::<gst::Buffer>().expect("signal arg");
let appsrc = element.imp();
Some(appsrc.push_buffer(&element, buffer).to_value())
Some(appsrc.push_buffer(buffer).to_value())
})
.build(),
/**
@ -519,7 +519,7 @@ impl ObjectImpl for AppSrc {
let element = args[0].get::<super::AppSrc>().expect("signal arg");
let appsrc = element.imp();
Some(appsrc.end_of_stream(&element).to_value())
Some(appsrc.end_of_stream().to_value())
})
.build(),
]
@ -528,13 +528,7 @@ impl ObjectImpl for AppSrc {
SIGNALS.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"context" => {
@ -561,7 +555,7 @@ impl ObjectImpl for AppSrc {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"context" => settings.context.to_value(),
@ -573,12 +567,12 @@ impl ObjectImpl for AppSrc {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.src_pad.gst_pad()).unwrap();
crate::set_element_flags(obj, gst::ElementFlags::SOURCE);
obj.set_element_flags(gst::ElementFlags::SOURCE);
}
}
@ -617,41 +611,40 @@ impl ElementImpl for AppSrc {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare(element).map_err(|err| {
element.post_error_message(err);
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::PlayingToPaused => {
self.pause(element).map_err(|_| gst::StateChangeError)?;
self.pause().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::ReadyToNull => {
self.unprepare(element);
self.unprepare();
}
_ => (),
}
let mut success = self.parent_change_state(element, transition)?;
let mut success = self.parent_change_state(transition)?;
match transition {
gst::StateChange::ReadyToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
}
gst::StateChange::PausedToPlaying => {
self.start(element).map_err(|_| gst::StateChangeError)?;
self.start().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::PlayingToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
}
gst::StateChange::PausedToReady => {
self.stop(element).map_err(|_| gst::StateChangeError)?;
self.stop().map_err(|_| gst::StateChangeError)?;
}
_ => (),
}

View file

@ -92,8 +92,8 @@ impl InputSelectorPadSinkHandler {
async fn handle_item(
&self,
pad: &PadSinkRef<'_>,
element: &super::InputSelector,
pad: &PadSinkRef<'_>,
mut buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let inputselector = element.imp();
@ -173,7 +173,7 @@ impl PadSinkHandler for InputSelectorPadSinkHandler {
let pad_weak = pad.downgrade();
async move {
let pad = pad_weak.upgrade().expect("PadSink no longer exists");
this.handle_item(&pad, &element, buffer).await
this.handle_item(&element, &pad, buffer).await
}
.boxed()
}
@ -193,7 +193,7 @@ impl PadSinkHandler for InputSelectorPadSinkHandler {
gst::log!(CAT, obj: pad.gst_pad(), "Handling buffer list {:?}", list);
// TODO: Ideally we would keep the list intact and forward it in one go
for buffer in list.iter_owned() {
this.handle_item(&pad, &element, buffer).await?;
this.handle_item(&element, &pad, buffer).await?;
}
Ok(gst::FlowSuccess::Ok)
@ -377,11 +377,11 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
impl InputSelector {
fn unprepare(&self, element: &super::InputSelector) {
fn unprepare(&self) {
let mut state = self.state.lock().unwrap();
gst::debug!(CAT, obj: element, "Unpreparing");
gst::debug!(CAT, imp: self, "Unpreparing");
*state = State::default();
gst::debug!(CAT, obj: element, "Unprepared");
gst::debug!(CAT, imp: self, "Unprepared");
}
}
@ -433,13 +433,7 @@ impl ObjectImpl for InputSelector {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"context" => {
let mut settings = self.settings.lock().unwrap();
@ -488,7 +482,7 @@ impl ObjectImpl for InputSelector {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"context" => {
let settings = self.settings.lock().unwrap();
@ -507,9 +501,10 @@ impl ObjectImpl for InputSelector {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.src_pad.gst_pad()).unwrap();
obj.set_element_flags(gst::ElementFlags::PROVIDE_CLOCK | gst::ElementFlags::REQUIRE_CLOCK);
}
@ -558,16 +553,15 @@ impl ElementImpl for InputSelector {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
if let gst::StateChange::ReadyToNull = transition {
self.unprepare(element);
self.unprepare();
}
let mut success = self.parent_change_state(element, transition)?;
let mut success = self.parent_change_state(transition)?;
match transition {
gst::StateChange::ReadyToPaused => {
@ -584,7 +578,6 @@ impl ElementImpl for InputSelector {
fn request_new_pad(
&self,
element: &Self::Type,
templ: &gst::PadTemplate,
_name: Option<String>,
_caps: Option<&gst::Caps>,
@ -595,7 +588,7 @@ impl ElementImpl for InputSelector {
gst::Pad::from_template(templ, Some(format!("sink_{}", pads.pad_serial).as_str()));
pads.pad_serial += 1;
sink_pad.set_active(true).unwrap();
element.add_pad(&sink_pad).unwrap();
self.instance().add_pad(&sink_pad).unwrap();
let sink_pad = PadSink::new(sink_pad, InputSelectorPadSinkHandler::default());
let ret = sink_pad.gst_pad().clone();
@ -608,22 +601,30 @@ impl ElementImpl for InputSelector {
drop(pads);
drop(state);
let _ = element.post_message(gst::message::Latency::builder().src(element).build());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
Some(ret)
}
fn release_pad(&self, element: &Self::Type, pad: &gst::Pad) {
fn release_pad(&self, pad: &gst::Pad) {
let mut pads = self.pads.lock().unwrap();
let sink_pad = pads.sink_pads.remove(pad).unwrap();
drop(sink_pad);
element.remove_pad(pad).unwrap();
self.instance().remove_pad(pad).unwrap();
drop(pads);
let _ = element.post_message(gst::message::Latency::builder().src(element).build());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
}
fn provide_clock(&self, _element: &Self::Type) -> Option<gst::Clock> {
fn provide_clock(&self) -> Option<gst::Clock> {
Some(gst::SystemClock::obtain())
}
}

View file

@ -1279,16 +1279,16 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
impl JitterBuffer {
fn clear_pt_map(&self, element: &super::JitterBuffer) {
gst::debug!(CAT, obj: element, "Clearing PT map");
fn clear_pt_map(&self) {
gst::debug!(CAT, imp: self, "Clearing PT map");
let mut state = self.state.lock().unwrap();
state.clock_rate = None;
state.jbuf.reset_skew();
}
fn prepare(&self, element: &super::JitterBuffer) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Preparing");
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Preparing");
let context = {
let settings = self.settings.lock().unwrap();
@ -1297,33 +1297,37 @@ impl JitterBuffer {
self.task
.prepare(
JitterBufferTask::new(element, &self.src_pad_handler, &self.sink_pad_handler),
JitterBufferTask::new(
&*self.instance(),
&self.src_pad_handler,
&self.sink_pad_handler,
),
context,
)
.block_on()?;
gst::debug!(CAT, obj: element, "Prepared");
gst::debug!(CAT, imp: self, "Prepared");
Ok(())
}
fn unprepare(&self, element: &super::JitterBuffer) {
gst::debug!(CAT, obj: element, "Unpreparing");
fn unprepare(&self) {
gst::debug!(CAT, imp: self, "Unpreparing");
self.task.unprepare().block_on().unwrap();
gst::debug!(CAT, obj: element, "Unprepared");
gst::debug!(CAT, imp: self, "Unprepared");
}
fn start(&self, element: &super::JitterBuffer) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Starting");
fn start(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Starting");
self.task.start().block_on()?;
gst::debug!(CAT, obj: element, "Started");
gst::debug!(CAT, imp: self, "Started");
Ok(())
}
fn stop(&self, element: &super::JitterBuffer) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Stopping");
fn stop(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Stopping");
self.task.stop().block_on()?;
gst::debug!(CAT, obj: element, "Stopped");
gst::debug!(CAT, imp: self, "Stopped");
Ok(())
}
}
@ -1410,7 +1414,7 @@ impl ObjectImpl for JitterBuffer {
.class_handler(|_, args| {
let element = args[0].get::<super::JitterBuffer>().expect("signal arg");
let jb = element.imp();
jb.clear_pt_map(&element);
jb.clear_pt_map();
None
})
.build(),
@ -1424,13 +1428,7 @@ impl ObjectImpl for JitterBuffer {
SIGNALS.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"latency" => {
let latency = {
@ -1444,7 +1442,11 @@ impl ObjectImpl for JitterBuffer {
let state = self.state.lock().unwrap();
state.jbuf.set_delay(latency);
let _ = obj.post_message(gst::message::Latency::builder().src(obj).build());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
}
"do-lost" => {
let mut settings = self.settings.lock().unwrap();
@ -1475,7 +1477,7 @@ impl ObjectImpl for JitterBuffer {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"latency" => {
let settings = self.settings.lock().unwrap();
@ -1514,9 +1516,10 @@ impl ObjectImpl for JitterBuffer {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.sink_pad.gst_pad()).unwrap();
obj.add_pad(self.src_pad.gst_pad()).unwrap();
obj.set_element_flags(gst::ElementFlags::PROVIDE_CLOCK | gst::ElementFlags::REQUIRE_CLOCK);
@ -1567,32 +1570,31 @@ impl ElementImpl for JitterBuffer {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare(element).map_err(|err| {
element.post_error_message(err);
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::PausedToReady => {
self.stop(element).map_err(|_| gst::StateChangeError)?;
self.stop().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::ReadyToNull => {
self.unprepare(element);
self.unprepare();
}
_ => (),
}
let mut success = self.parent_change_state(element, transition)?;
let mut success = self.parent_change_state(transition)?;
match transition {
gst::StateChange::ReadyToPaused => {
self.start(element).map_err(|_| gst::StateChangeError)?;
self.start().map_err(|_| gst::StateChangeError)?;
success = gst::StateChangeSuccess::NoPreroll;
}
gst::StateChange::PlayingToPaused => {
@ -1604,7 +1606,7 @@ impl ElementImpl for JitterBuffer {
Ok(success)
}
fn provide_clock(&self, _element: &Self::Type) -> Option<gst::Clock> {
fn provide_clock(&self) -> Option<gst::Clock> {
Some(gst::SystemClock::obtain())
}
}

View file

@ -28,7 +28,6 @@ mod jitterbuffer;
mod proxy;
mod queue;
use glib::translate::*;
use gst::glib;
fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
@ -55,34 +54,3 @@ gst::plugin_define!(
env!("CARGO_PKG_REPOSITORY"),
env!("BUILD_REL_DATE")
);
pub fn set_element_flags<T: glib::IsA<gst::Object> + glib::IsA<gst::Element>>(
element: &T,
flags: gst::ElementFlags,
) {
unsafe {
let ptr: *mut gst::ffi::GstObject = element.as_ptr() as *mut _;
let _guard = MutexGuard::lock(&(*ptr).lock);
(*ptr).flags |= flags.into_glib();
}
}
#[must_use = "if unused the Mutex will immediately unlock"]
struct MutexGuard<'a>(&'a glib::ffi::GMutex);
impl<'a> MutexGuard<'a> {
pub fn lock(mutex: &'a glib::ffi::GMutex) -> Self {
unsafe {
glib::ffi::g_mutex_lock(mut_override(mutex));
}
MutexGuard(mutex)
}
}
impl<'a> Drop for MutexGuard<'a> {
fn drop(&mut self) {
unsafe {
glib::ffi::g_mutex_unlock(mut_override(self.0));
}
}
}

View file

@ -227,9 +227,7 @@ impl PadSinkHandler for ProxySinkPadHandler {
let pad = pad_weak.upgrade().expect("PadSink no longer exists");
gst::log!(SINK_CAT, obj: pad.gst_pad(), "Handling {:?}", buffer);
let proxysink = element.imp();
proxysink
.enqueue_item(&element, DataQueueItem::Buffer(buffer))
.await
proxysink.enqueue_item(DataQueueItem::Buffer(buffer)).await
}
.boxed()
}
@ -248,7 +246,7 @@ impl PadSinkHandler for ProxySinkPadHandler {
gst::log!(SINK_CAT, obj: pad.gst_pad(), "Handling {:?}", list);
let proxysink = element.imp();
proxysink
.enqueue_item(&element, DataQueueItem::BufferList(list))
.enqueue_item(DataQueueItem::BufferList(list))
.await
}
.boxed()
@ -258,7 +256,7 @@ impl PadSinkHandler for ProxySinkPadHandler {
&self,
pad: &PadSinkRef,
proxysink: &ProxySink,
element: &gst::Element,
_element: &gst::Element,
event: gst::Event,
) -> bool {
use gst::EventView;
@ -277,7 +275,7 @@ impl PadSinkHandler for ProxySinkPadHandler {
};
if let EventView::FlushStart(..) = event.view() {
proxysink.stop(element.downcast_ref::<super::ProxySink>().unwrap());
proxysink.stop();
}
if let Some(src_pad) = src_pad {
@ -311,13 +309,13 @@ impl PadSinkHandler for ProxySinkPadHandler {
let _ =
element.post_message(gst::message::Eos::builder().src(&element).build());
}
EventView::FlushStop(..) => proxysink.start(&element),
EventView::FlushStop(..) => proxysink.start(),
_ => (),
}
gst::log!(SINK_CAT, obj: pad.gst_pad(), "Queuing serialized {:?}", event);
proxysink
.enqueue_item(&element, DataQueueItem::Event(event))
.enqueue_item(DataQueueItem::Event(event))
.await
.is_ok()
}
@ -341,13 +339,13 @@ static SINK_CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
impl ProxySink {
async fn schedule_pending_queue(&self, element: &super::ProxySink) {
async fn schedule_pending_queue(&self) {
loop {
let more_queue_space_receiver = {
let proxy_ctx = self.proxy_ctx.lock().unwrap();
let mut shared_ctx = proxy_ctx.as_ref().unwrap().lock_shared();
gst::log!(SINK_CAT, obj: element, "Trying to empty pending queue");
gst::log!(SINK_CAT, imp: self, "Trying to empty pending queue");
let ProxyContextInner {
pending_queue: ref mut pq,
@ -372,7 +370,7 @@ impl ProxySink {
receiver
} else {
gst::log!(SINK_CAT, obj: element, "Pending queue is empty now");
gst::log!(SINK_CAT, imp: self, "Pending queue is empty now");
*pq = None;
return;
}
@ -383,22 +381,18 @@ impl ProxySink {
receiver
}
} else {
gst::log!(SINK_CAT, obj: element, "Flushing, dropping pending queue");
gst::log!(SINK_CAT, imp: self, "Flushing, dropping pending queue");
*pq = None;
return;
}
};
gst::log!(SINK_CAT, obj: element, "Waiting for more queue space");
gst::log!(SINK_CAT, imp: self, "Waiting for more queue space");
let _ = more_queue_space_receiver.await;
}
}
async fn enqueue_item(
&self,
element: &super::ProxySink,
item: DataQueueItem,
) -> Result<gst::FlowSuccess, gst::FlowError> {
async fn enqueue_item(&self, item: DataQueueItem) -> Result<gst::FlowSuccess, gst::FlowError> {
let wait_fut = {
let proxy_ctx = self.proxy_ctx.lock().unwrap();
let mut shared_ctx = proxy_ctx.as_ref().unwrap().lock_shared();
@ -463,18 +457,18 @@ impl ProxySink {
gst::log!(
SINK_CAT,
obj: element,
imp: self,
"Proxy is full - Pushing first item on pending queue"
);
if schedule_now {
gst::log!(SINK_CAT, obj: element, "Scheduling pending queue now");
gst::log!(SINK_CAT, imp: self, "Scheduling pending queue now");
pending_queue.scheduled = true;
let wait_fut = self.schedule_pending_queue(element);
let wait_fut = self.schedule_pending_queue();
Some(wait_fut)
} else {
gst::log!(SINK_CAT, obj: element, "Scheduling pending queue later");
gst::log!(SINK_CAT, imp: self, "Scheduling pending queue later");
None
}
@ -494,11 +488,7 @@ impl ProxySink {
};
if let Some(wait_fut) = wait_fut {
gst::log!(
SINK_CAT,
obj: element,
"Blocking until queue has space again"
);
gst::log!(SINK_CAT, imp: self, "Blocking until queue has space again");
wait_fut.await;
}
@ -507,8 +497,8 @@ impl ProxySink {
shared_ctx.last_res
}
fn prepare(&self, element: &super::ProxySink) -> Result<(), gst::ErrorMessage> {
gst::debug!(SINK_CAT, obj: element, "Preparing");
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(SINK_CAT, imp: self, "Preparing");
let proxy_context = self.settings.lock().unwrap().proxy_context.to_string();
@ -527,22 +517,22 @@ impl ProxySink {
*self.proxy_ctx.lock().unwrap() = Some(proxy_ctx);
gst::debug!(SINK_CAT, obj: element, "Prepared");
gst::debug!(SINK_CAT, imp: self, "Prepared");
Ok(())
}
fn unprepare(&self, element: &super::ProxySink) {
gst::debug!(SINK_CAT, obj: element, "Unpreparing");
fn unprepare(&self) {
gst::debug!(SINK_CAT, imp: self, "Unpreparing");
*self.proxy_ctx.lock().unwrap() = None;
gst::debug!(SINK_CAT, obj: element, "Unprepared");
gst::debug!(SINK_CAT, imp: self, "Unprepared");
}
fn start(&self, element: &super::ProxySink) {
fn start(&self) {
let proxy_ctx = self.proxy_ctx.lock().unwrap();
let mut shared_ctx = proxy_ctx.as_ref().unwrap().lock_shared();
gst::debug!(SINK_CAT, obj: element, "Starting");
gst::debug!(SINK_CAT, imp: self, "Starting");
{
let settings = self.settings.lock().unwrap();
@ -552,19 +542,19 @@ impl ProxySink {
shared_ctx.last_res = Ok(gst::FlowSuccess::Ok);
gst::debug!(SINK_CAT, obj: element, "Started");
gst::debug!(SINK_CAT, imp: self, "Started");
}
fn stop(&self, element: &super::ProxySink) {
fn stop(&self) {
let proxy_ctx = self.proxy_ctx.lock().unwrap();
let mut shared_ctx = proxy_ctx.as_ref().unwrap().lock_shared();
gst::debug!(SINK_CAT, obj: element, "Stopping");
gst::debug!(SINK_CAT, imp: self, "Stopping");
let _ = shared_ctx.pending_queue.take();
shared_ctx.last_res = Err(gst::FlowError::Flushing);
gst::debug!(SINK_CAT, obj: element, "Stopped");
gst::debug!(SINK_CAT, imp: self, "Stopped");
}
}
@ -599,13 +589,7 @@ impl ObjectImpl for ProxySink {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"proxy-context" => {
@ -618,7 +602,7 @@ impl ObjectImpl for ProxySink {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"proxy-context" => settings.proxy_context.to_value(),
@ -626,12 +610,12 @@ impl ObjectImpl for ProxySink {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.sink_pad.gst_pad()).unwrap();
crate::set_element_flags(obj, gst::ElementFlags::SINK);
obj.set_element_flags(gst::ElementFlags::SINK);
}
}
@ -671,31 +655,30 @@ impl ElementImpl for ProxySink {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(SINK_CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(SINK_CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare(element).map_err(|err| {
element.post_error_message(err);
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::PausedToReady => {
self.stop(element);
self.stop();
}
gst::StateChange::ReadyToNull => {
self.unprepare(element);
self.unprepare();
}
_ => (),
}
let success = self.parent_change_state(element, transition)?;
let success = self.parent_change_state(transition)?;
if transition == gst::StateChange::ReadyToPaused {
self.start(element);
self.start();
}
Ok(success)
@ -992,8 +975,8 @@ static SRC_CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
impl ProxySrc {
fn prepare(&self, element: &super::ProxySrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(SRC_CAT, obj: element, "Preparing");
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(SRC_CAT, imp: self, "Preparing");
let settings = self.settings.lock().unwrap().clone();
@ -1012,7 +995,7 @@ impl ProxySrc {
})?;
let dataqueue = DataQueue::new(
&element.clone().upcast(),
&self.instance().clone().upcast(),
self.src_pad.gst_pad(),
if settings.max_size_buffers == 0 {
None
@ -1044,16 +1027,19 @@ impl ProxySrc {
*self.dataqueue.lock().unwrap() = Some(dataqueue.clone());
self.task
.prepare(ProxySrcTask::new(element.clone(), dataqueue), ts_ctx)
.prepare(
ProxySrcTask::new(self.instance().clone(), dataqueue),
ts_ctx,
)
.block_on()?;
gst::debug!(SRC_CAT, obj: element, "Prepared");
gst::debug!(SRC_CAT, imp: self, "Prepared");
Ok(())
}
fn unprepare(&self, element: &super::ProxySrc) {
gst::debug!(SRC_CAT, obj: element, "Unpreparing");
fn unprepare(&self) {
gst::debug!(SRC_CAT, imp: self, "Unpreparing");
{
let settings = self.settings.lock().unwrap();
@ -1066,27 +1052,27 @@ impl ProxySrc {
*self.dataqueue.lock().unwrap() = None;
*self.proxy_ctx.lock().unwrap() = None;
gst::debug!(SRC_CAT, obj: element, "Unprepared");
gst::debug!(SRC_CAT, imp: self, "Unprepared");
}
fn stop(&self, element: &super::ProxySrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(SRC_CAT, obj: element, "Stopping");
fn stop(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(SRC_CAT, imp: self, "Stopping");
self.task.stop().await_maybe_on_context()?;
gst::debug!(SRC_CAT, obj: element, "Stopped");
gst::debug!(SRC_CAT, imp: self, "Stopped");
Ok(())
}
fn start(&self, element: &super::ProxySrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(SRC_CAT, obj: element, "Starting");
fn start(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(SRC_CAT, imp: self, "Starting");
self.task.start().await_maybe_on_context()?;
gst::debug!(SRC_CAT, obj: element, "Started");
gst::debug!(SRC_CAT, imp: self, "Started");
Ok(())
}
fn pause(&self, element: &super::ProxySrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(SRC_CAT, obj: element, "Pausing");
fn pause(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(SRC_CAT, imp: self, "Pausing");
self.task.pause().block_on()?;
gst::debug!(SRC_CAT, obj: element, "Paused");
gst::debug!(SRC_CAT, imp: self, "Paused");
Ok(())
}
}
@ -1153,13 +1139,7 @@ impl ObjectImpl for ProxySrc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"max-size-buffers" => {
@ -1193,7 +1173,7 @@ impl ObjectImpl for ProxySrc {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"max-size-buffers" => settings.max_size_buffers.to_value(),
@ -1206,12 +1186,12 @@ impl ObjectImpl for ProxySrc {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.src_pad.gst_pad()).unwrap();
crate::set_element_flags(obj, gst::ElementFlags::SOURCE);
obj.set_element_flags(gst::ElementFlags::SOURCE);
}
}
@ -1251,41 +1231,40 @@ impl ElementImpl for ProxySrc {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(SRC_CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(SRC_CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare(element).map_err(|err| {
element.post_error_message(err);
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::PlayingToPaused => {
self.pause(element).map_err(|_| gst::StateChangeError)?;
self.pause().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::ReadyToNull => {
self.unprepare(element);
self.unprepare();
}
_ => (),
}
let mut success = self.parent_change_state(element, transition)?;
let mut success = self.parent_change_state(transition)?;
match transition {
gst::StateChange::ReadyToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
}
gst::StateChange::PausedToPlaying => {
self.start(element).map_err(|_| gst::StateChangeError)?;
self.start().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::PlayingToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
}
gst::StateChange::PausedToReady => {
self.stop(element).map_err(|_| gst::StateChangeError)?;
self.stop().map_err(|_| gst::StateChangeError)?;
}
_ => (),
}

View file

@ -96,9 +96,7 @@ impl PadSinkHandler for QueuePadSinkHandler {
let pad = pad_weak.upgrade().expect("PadSink no longer exists");
gst::log!(CAT, obj: pad.gst_pad(), "Handling {:?}", buffer);
let queue = element.imp();
queue
.enqueue_item(&element, DataQueueItem::Buffer(buffer))
.await
queue.enqueue_item(DataQueueItem::Buffer(buffer)).await
}
.boxed()
}
@ -116,9 +114,7 @@ impl PadSinkHandler for QueuePadSinkHandler {
let pad = pad_weak.upgrade().expect("PadSink no longer exists");
gst::log!(CAT, obj: pad.gst_pad(), "Handling {:?}", list);
let queue = element.imp();
queue
.enqueue_item(&element, DataQueueItem::BufferList(list))
.await
queue.enqueue_item(DataQueueItem::BufferList(list)).await
}
.boxed()
}
@ -183,7 +179,7 @@ impl PadSinkHandler for QueuePadSinkHandler {
gst::log!(CAT, obj: pad.gst_pad(), "Queuing serialized {:?}", event);
queue
.enqueue_item(&element, DataQueueItem::Event(event))
.enqueue_item(DataQueueItem::Event(event))
.await
.is_ok()
}
@ -495,7 +491,7 @@ impl Queue {
/* Schedules emptying of the pending queue. If there is an upstream
* TaskContext, the new task is spawned, it is otherwise
* returned, for the caller to block on */
async fn schedule_pending_queue(&self, element: &super::Queue) {
async fn schedule_pending_queue(&self) {
loop {
let more_queue_space_receiver = {
let dataqueue = self.dataqueue.lock().unwrap();
@ -504,7 +500,7 @@ impl Queue {
}
let mut pending_queue_grd = self.pending_queue.lock().unwrap();
gst::log!(CAT, obj: element, "Trying to empty pending queue");
gst::log!(CAT, imp: self, "Trying to empty pending queue");
if let Some(pending_queue) = pending_queue_grd.as_mut() {
let mut failed_item = None;
@ -521,30 +517,26 @@ impl Queue {
receiver
} else {
gst::log!(CAT, obj: element, "Pending queue is empty now");
gst::log!(CAT, imp: self, "Pending queue is empty now");
*pending_queue_grd = None;
return;
}
} else {
gst::log!(CAT, obj: element, "Flushing, dropping pending queue");
gst::log!(CAT, imp: self, "Flushing, dropping pending queue");
return;
}
};
gst::log!(CAT, obj: element, "Waiting for more queue space");
gst::log!(CAT, imp: self, "Waiting for more queue space");
let _ = more_queue_space_receiver.await;
}
}
async fn enqueue_item(
&self,
element: &super::Queue,
item: DataQueueItem,
) -> Result<gst::FlowSuccess, gst::FlowError> {
async fn enqueue_item(&self, item: DataQueueItem) -> Result<gst::FlowSuccess, gst::FlowError> {
let wait_fut = {
let dataqueue = self.dataqueue.lock().unwrap();
let dataqueue = dataqueue.as_ref().ok_or_else(|| {
gst::error!(CAT, obj: element, "No DataQueue");
gst::error!(CAT, imp: self, "No DataQueue");
gst::FlowError::Error
})?;
@ -573,18 +565,18 @@ impl Queue {
gst::log!(
CAT,
obj: element,
imp: self,
"Queue is full - Pushing first item on pending queue"
);
if schedule_now {
gst::log!(CAT, obj: element, "Scheduling pending queue now");
gst::log!(CAT, imp: self, "Scheduling pending queue now");
pending_queue.as_mut().unwrap().scheduled = true;
let wait_fut = self.schedule_pending_queue(element);
let wait_fut = self.schedule_pending_queue();
Some(wait_fut)
} else {
gst::log!(CAT, obj: element, "Scheduling pending queue later");
gst::log!(CAT, imp: self, "Scheduling pending queue later");
None
}
} else {
@ -597,20 +589,20 @@ impl Queue {
};
if let Some(wait_fut) = wait_fut {
gst::log!(CAT, obj: element, "Blocking until queue has space again");
gst::log!(CAT, imp: self, "Blocking until queue has space again");
wait_fut.await;
}
*self.last_res.lock().unwrap()
}
fn prepare(&self, element: &super::Queue) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Preparing");
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Preparing");
let settings = self.settings.lock().unwrap().clone();
let dataqueue = DataQueue::new(
&element.clone().upcast(),
&self.instance().clone().upcast(),
self.src_pad.gst_pad(),
if settings.max_size_buffers == 0 {
None
@ -640,16 +632,16 @@ impl Queue {
})?;
self.task
.prepare(QueueTask::new(element.clone(), dataqueue), context)
.prepare(QueueTask::new(self.instance().clone(), dataqueue), context)
.block_on()?;
gst::debug!(CAT, obj: element, "Prepared");
gst::debug!(CAT, imp: self, "Prepared");
Ok(())
}
fn unprepare(&self, element: &super::Queue) {
gst::debug!(CAT, obj: element, "Unpreparing");
fn unprepare(&self) {
gst::debug!(CAT, imp: self, "Unpreparing");
self.task.unprepare().block_on().unwrap();
@ -658,20 +650,20 @@ impl Queue {
*self.last_res.lock().unwrap() = Ok(gst::FlowSuccess::Ok);
gst::debug!(CAT, obj: element, "Unprepared");
gst::debug!(CAT, imp: self, "Unprepared");
}
fn stop(&self, element: &super::Queue) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Stopping");
fn stop(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Stopping");
self.task.stop().await_maybe_on_context()?;
gst::debug!(CAT, obj: element, "Stopped");
gst::debug!(CAT, imp: self, "Stopped");
Ok(())
}
fn start(&self, element: &super::Queue) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Starting");
fn start(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Starting");
self.task.start().await_maybe_on_context()?;
gst::debug!(CAT, obj: element, "Started");
gst::debug!(CAT, imp: self, "Started");
Ok(())
}
}
@ -738,13 +730,7 @@ impl ObjectImpl for Queue {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"max-size-buffers" => {
@ -772,7 +758,7 @@ impl ObjectImpl for Queue {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"max-size-buffers" => settings.max_size_buffers.to_value(),
@ -784,9 +770,10 @@ impl ObjectImpl for Queue {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.sink_pad.gst_pad()).unwrap();
obj.add_pad(self.src_pad.gst_pad()).unwrap();
}
@ -836,31 +823,30 @@ impl ElementImpl for Queue {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare(element).map_err(|err| {
element.post_error_message(err);
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::PausedToReady => {
self.stop(element).map_err(|_| gst::StateChangeError)?;
self.stop().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::ReadyToNull => {
self.unprepare(element);
self.unprepare();
}
_ => (),
}
let success = self.parent_change_state(element, transition)?;
let success = self.parent_change_state(transition)?;
if transition == gst::StateChange::ReadyToPaused {
self.start(element).map_err(|_| gst::StateChangeError)?;
self.start().map_err(|_| gst::StateChangeError)?;
}
Ok(success)

View file

@ -398,8 +398,9 @@ impl PadSrc {
"Panic in PadSrc activate"
))
},
move |imp, element| {
move |imp| {
let this_ref = PadSrcRef::new(inner_arc);
let element = imp.instance();
handler.src_activate(
&this_ref,
imp,
@ -424,8 +425,9 @@ impl PadSrc {
"Panic in PadSrc activatemode"
))
},
move |imp, element| {
move |imp| {
let this_ref = PadSrcRef::new(inner_arc);
let element = imp.instance();
this_ref.activate_mode_hook(mode, active)?;
handler.src_activatemode(
&this_ref,
@ -449,8 +451,9 @@ impl PadSrc {
H::ElementImpl::catch_panic_pad_function(
parent,
|| Err(FlowError::Error),
move |imp, element| {
move |imp| {
let this_ref = PadSrcRef::new(inner_arc);
let element = imp.instance();
handler.src_event_full(
&this_ref,
imp,
@ -469,8 +472,9 @@ impl PadSrc {
H::ElementImpl::catch_panic_pad_function(
parent,
|| false,
move |imp, element| {
move |imp| {
let this_ref = PadSrcRef::new(inner_arc);
let element = imp.instance();
if !query.is_serialized() {
handler.src_query(&this_ref, imp, element.dynamic_cast_ref::<gst::Element>().unwrap(), query)
} else {
@ -807,8 +811,9 @@ impl PadSink {
"Panic in PadSink activate"
))
},
move |imp, element| {
move |imp| {
let this_ref = PadSinkRef::new(inner_arc);
let element = imp.instance();
handler.sink_activate(
&this_ref,
imp,
@ -833,8 +838,9 @@ impl PadSink {
"Panic in PadSink activatemode"
))
},
move |imp, element| {
move |imp| {
let this_ref = PadSinkRef::new(inner_arc);
let element = imp.instance();
this_ref.activate_mode_hook(mode, active)?;
handler.sink_activatemode(
@ -857,7 +863,8 @@ impl PadSink {
H::ElementImpl::catch_panic_pad_function(
parent,
|| Err(FlowError::Error),
move |imp, element| {
move |imp| {
let element = imp.instance();
if let Some((ctx, task_id)) = Context::current_task() {
let this_weak = PadSinkWeak(Arc::downgrade(&inner_arc));
let handler = handler.clone();
@ -898,7 +905,8 @@ impl PadSink {
H::ElementImpl::catch_panic_pad_function(
parent,
|| Err(FlowError::Error),
move |imp, element| {
move |imp| {
let element = imp.instance();
if let Some((ctx, task_id)) = Context::current_task() {
let this_weak = PadSinkWeak(Arc::downgrade(&inner_arc));
let handler = handler.clone();
@ -943,7 +951,8 @@ impl PadSink {
H::ElementImpl::catch_panic_pad_function(
parent,
|| Err(FlowError::Error),
move |imp, element| {
move |imp| {
let element = imp.instance();
if event.is_serialized() {
if let Some((ctx, task_id)) = Context::current_task() {
let this_weak = PadSinkWeak(Arc::downgrade(&inner_arc));
@ -1001,8 +1010,9 @@ impl PadSink {
H::ElementImpl::catch_panic_pad_function(
parent,
|| false,
move |imp, element| {
move |imp| {
let this_ref = PadSinkRef::new(inner_arc);
let element = imp.instance();
if !query.is_serialized() {
handler.sink_query(&this_ref, imp, element.dynamic_cast_ref::<gst::Element>().unwrap(), query)
} else {

View file

@ -408,8 +408,8 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
impl TcpClientSrc {
fn prepare(&self, element: &super::TcpClientSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Preparing");
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Preparing");
let settings = self.settings.lock().unwrap().clone();
let context =
@ -459,40 +459,40 @@ impl TcpClientSrc {
let _ = self
.task
.prepare(
TcpClientSrcTask::new(element.clone(), saddr, buffer_pool),
TcpClientSrcTask::new(self.instance().clone(), saddr, buffer_pool),
context,
)
.check()?;
gst::debug!(CAT, obj: element, "Preparing asynchronously");
gst::debug!(CAT, imp: self, "Preparing asynchronously");
Ok(())
}
fn unprepare(&self, element: &super::TcpClientSrc) {
gst::debug!(CAT, obj: element, "Unpreparing");
fn unprepare(&self) {
gst::debug!(CAT, imp: self, "Unpreparing");
self.task.unprepare().block_on().unwrap();
gst::debug!(CAT, obj: element, "Unprepared");
gst::debug!(CAT, imp: self, "Unprepared");
}
fn stop(&self, element: &super::TcpClientSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Stopping");
fn stop(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Stopping");
self.task.stop().block_on()?;
gst::debug!(CAT, obj: element, "Stopped");
gst::debug!(CAT, imp: self, "Stopped");
Ok(())
}
fn start(&self, element: &super::TcpClientSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Starting");
fn start(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Starting");
self.task.start().block_on()?;
gst::debug!(CAT, obj: element, "Started");
gst::debug!(CAT, imp: self, "Started");
Ok(())
}
fn pause(&self, element: &super::TcpClientSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Pausing");
fn pause(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Pausing");
self.task.pause().block_on()?;
gst::debug!(CAT, obj: element, "Paused");
gst::debug!(CAT, imp: self, "Paused");
Ok(())
}
}
@ -558,13 +558,7 @@ impl ObjectImpl for TcpClientSrc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"host" => {
@ -594,7 +588,7 @@ impl ObjectImpl for TcpClientSrc {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"host" => settings.host.to_value(),
@ -607,12 +601,12 @@ impl ObjectImpl for TcpClientSrc {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.src_pad.gst_pad()).unwrap();
crate::set_element_flags(obj, gst::ElementFlags::SOURCE);
obj.set_element_flags(gst::ElementFlags::SOURCE);
}
}
@ -651,41 +645,40 @@ impl ElementImpl for TcpClientSrc {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare(element).map_err(|err| {
element.post_error_message(err);
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::PlayingToPaused => {
self.pause(element).map_err(|_| gst::StateChangeError)?;
self.pause().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::ReadyToNull => {
self.unprepare(element);
self.unprepare();
}
_ => (),
}
let mut success = self.parent_change_state(element, transition)?;
let mut success = self.parent_change_state(transition)?;
match transition {
gst::StateChange::ReadyToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
}
gst::StateChange::PausedToPlaying => {
self.start(element).map_err(|_| gst::StateChangeError)?;
self.start().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::PlayingToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
}
gst::StateChange::PausedToReady => {
self.stop(element).map_err(|_| gst::StateChangeError)?;
self.stop().map_err(|_| gst::StateChangeError)?;
}
_ => (),
}

View file

@ -838,8 +838,8 @@ impl UdpSink {
self.item_sender.lock().unwrap().as_ref().unwrap().clone()
}
fn prepare(&self, element: &super::UdpSink) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Preparing");
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Preparing");
let context = {
let settings = self.settings.lock().unwrap();
@ -855,39 +855,37 @@ impl UdpSink {
// Enable backpressure for items
let (item_sender, item_receiver) = flume::bounded(0);
let (cmd_sender, cmd_receiver) = flume::unbounded();
let task_impl = UdpSinkTask::new(element, item_receiver, cmd_receiver);
let task_impl = UdpSinkTask::new(&*self.instance(), item_receiver, cmd_receiver);
self.task.prepare(task_impl, context).block_on()?;
*self.item_sender.lock().unwrap() = Some(item_sender);
*self.cmd_sender.lock().unwrap() = Some(cmd_sender);
gst::debug!(CAT, obj: element, "Started preparation");
gst::debug!(CAT, imp: self, "Started preparation");
Ok(())
}
fn unprepare(&self, element: &super::UdpSink) {
gst::debug!(CAT, obj: element, "Unpreparing");
fn unprepare(&self) {
gst::debug!(CAT, imp: self, "Unpreparing");
self.task.unprepare().block_on().unwrap();
gst::debug!(CAT, obj: element, "Unprepared");
gst::debug!(CAT, imp: self, "Unprepared");
}
fn stop(&self, element: &super::UdpSink) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Stopping");
fn stop(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Stopping");
self.task.stop().block_on()?;
gst::debug!(CAT, obj: element, "Stopped");
gst::debug!(CAT, imp: self, "Stopped");
Ok(())
}
fn start(&self, element: &super::UdpSink) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Starting");
fn start(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Starting");
self.task.start().block_on()?;
gst::debug!(CAT, obj: element, "Started");
gst::debug!(CAT, imp: self, "Started");
Ok(())
}
}
impl UdpSink {
fn add_client(&self, settings: &mut Settings, client: SocketAddr) {
settings.clients.insert(client);
if let Some(cmd_sender) = self.cmd_sender.lock().unwrap().as_mut() {
@ -919,10 +917,10 @@ impl UdpSink {
}
}
fn try_into_socket_addr(element: &super::UdpSink, host: &str, port: i32) -> Result<SocketAddr, ()> {
fn try_into_socket_addr(imp: &UdpSink, host: &str, port: i32) -> Result<SocketAddr, ()> {
let addr: IpAddr = match host.parse() {
Err(err) => {
gst::error!(CAT, obj: element, "Failed to parse host {}: {}", host, err);
gst::error!(CAT, imp: imp, "Failed to parse host {}: {}", host, err);
return Err(());
}
Ok(addr) => addr,
@ -930,7 +928,7 @@ fn try_into_socket_addr(element: &super::UdpSink, host: &str, port: i32) -> Resu
let port: u16 = match port.try_into() {
Err(err) => {
gst::error!(CAT, obj: element, "Invalid port {}: {}", port, err);
gst::error!(CAT, imp: imp, "Invalid port {}: {}", port, err);
return Err(());
}
Ok(port) => port,
@ -1071,9 +1069,9 @@ impl ObjectImpl for UdpSink {
let element = args[0].get::<super::UdpSink>().expect("signal arg");
let host = args[1].get::<String>().expect("signal arg");
let port = args[2].get::<i32>().expect("signal arg");
let udpsink = element.imp();
if let Ok(addr) = try_into_socket_addr(&element, &host, port) {
let udpsink = element.imp();
if let Ok(addr) = try_into_socket_addr(udpsink, &host, port) {
let mut settings = udpsink.settings.lock().unwrap();
udpsink.add_client(&mut settings, addr);
}
@ -1088,9 +1086,9 @@ impl ObjectImpl for UdpSink {
let element = args[0].get::<super::UdpSink>().expect("signal arg");
let host = args[1].get::<String>().expect("signal arg");
let port = args[2].get::<i32>().expect("signal arg");
let udpsink = element.imp();
if let Ok(addr) = try_into_socket_addr(&element, &host, port) {
let udpsink = element.imp();
if let Ok(addr) = try_into_socket_addr(udpsink, &host, port) {
let mut settings = udpsink.settings.lock().unwrap();
udpsink.remove_client(&mut settings, addr);
}
@ -1116,13 +1114,7 @@ impl ObjectImpl for UdpSink {
SIGNALS.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"sync" => {
@ -1196,9 +1188,9 @@ impl ObjectImpl for UdpSink {
rsplit[0]
.parse::<i32>()
.map_err(|err| {
gst::error!(CAT, obj: obj, "Invalid port {}: {}", rsplit[0], err);
gst::error!(CAT, imp: self, "Invalid port {}: {}", rsplit[0], err);
})
.and_then(|port| try_into_socket_addr(obj, rsplit[1], port))
.and_then(|port| try_into_socket_addr(self, rsplit[1], port))
.ok()
} else {
None
@ -1222,7 +1214,7 @@ impl ObjectImpl for UdpSink {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"sync" => settings.sync.to_value(),
@ -1268,12 +1260,12 @@ impl ObjectImpl for UdpSink {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.sink_pad.gst_pad()).unwrap();
crate::set_element_flags(obj, gst::ElementFlags::SINK);
obj.set_element_flags(gst::ElementFlags::SINK);
}
}
@ -1313,34 +1305,33 @@ impl ElementImpl for UdpSink {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare(element).map_err(|err| {
element.post_error_message(err);
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::ReadyToPaused => {
self.start(element).map_err(|_| gst::StateChangeError)?;
self.start().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::PausedToReady => {
self.stop(element).map_err(|_| gst::StateChangeError)?;
self.stop().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::ReadyToNull => {
self.unprepare(element);
self.unprepare();
}
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
fn send_event(&self, _element: &Self::Type, event: gst::Event) -> bool {
fn send_event(&self, event: gst::Event) -> bool {
match event.view() {
EventView::Latency(ev) => {
let latency = Some(ev.latency());

View file

@ -574,8 +574,8 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
impl UdpSrc {
fn prepare(&self, element: &super::UdpSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Preparing");
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Preparing");
let settings = self.settings.lock().unwrap();
let context =
@ -589,38 +589,38 @@ impl UdpSrc {
*self.configured_caps.lock().unwrap() = None;
self.task
.prepare(UdpSrcTask::new(element.clone()), context)
.prepare(UdpSrcTask::new(self.instance().clone()), context)
.block_on()?;
gst::debug!(CAT, obj: element, "Prepared");
gst::debug!(CAT, imp: self, "Prepared");
Ok(())
}
fn unprepare(&self, element: &super::UdpSrc) {
gst::debug!(CAT, obj: element, "Unpreparing");
fn unprepare(&self) {
gst::debug!(CAT, imp: self, "Unpreparing");
self.task.unprepare().block_on().unwrap();
gst::debug!(CAT, obj: element, "Unprepared");
gst::debug!(CAT, imp: self, "Unprepared");
}
fn stop(&self, element: &super::UdpSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Stopping");
fn stop(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Stopping");
self.task.stop().block_on()?;
gst::debug!(CAT, obj: element, "Stopped");
gst::debug!(CAT, imp: self, "Stopped");
Ok(())
}
fn start(&self, element: &super::UdpSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Starting");
fn start(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Starting");
self.task.start().block_on()?;
gst::debug!(CAT, obj: element, "Started");
gst::debug!(CAT, imp: self, "Started");
Ok(())
}
fn pause(&self, element: &super::UdpSrc) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Pausing");
fn pause(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Pausing");
self.task.pause().block_on()?;
gst::debug!(CAT, obj: element, "Paused");
gst::debug!(CAT, imp: self, "Paused");
Ok(())
}
}
@ -716,13 +716,7 @@ impl ObjectImpl for UdpSrc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"address" => {
@ -767,7 +761,7 @@ impl ObjectImpl for UdpSrc {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"address" => settings.address.to_value(),
@ -792,12 +786,12 @@ impl ObjectImpl for UdpSrc {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.src_pad.gst_pad()).unwrap();
crate::set_element_flags(obj, gst::ElementFlags::SOURCE);
obj.set_element_flags(gst::ElementFlags::SOURCE);
}
}
@ -836,41 +830,40 @@ impl ElementImpl for UdpSrc {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare(element).map_err(|err| {
element.post_error_message(err);
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::PlayingToPaused => {
self.pause(element).map_err(|_| gst::StateChangeError)?;
self.pause().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::ReadyToNull => {
self.unprepare(element);
self.unprepare();
}
_ => (),
}
let mut success = self.parent_change_state(element, transition)?;
let mut success = self.parent_change_state(transition)?;
match transition {
gst::StateChange::ReadyToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
}
gst::StateChange::PausedToPlaying => {
self.start(element).map_err(|_| gst::StateChangeError)?;
self.start().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::PlayingToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
}
gst::StateChange::PausedToReady => {
self.stop(element).map_err(|_| gst::StateChangeError)?;
self.stop().map_err(|_| gst::StateChangeError)?;
}
_ => (),
}

View file

@ -230,8 +230,8 @@ mod imp_src {
}
}
fn prepare(&self, element: &super::ElementSrcTest) -> Result<(), gst::ErrorMessage> {
gst::debug!(SRC_CAT, obj: element, "Preparing");
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(SRC_CAT, imp: self, "Preparing");
let settings = self.settings.lock().unwrap().clone();
let context =
@ -246,39 +246,42 @@ mod imp_src {
*self.sender.lock().unwrap() = Some(sender);
self.task
.prepare(ElementSrcTestTask::new(element.clone(), receiver), context)
.prepare(
ElementSrcTestTask::new(self.instance().clone(), receiver),
context,
)
.block_on()?;
gst::debug!(SRC_CAT, obj: element, "Prepared");
gst::debug!(SRC_CAT, imp: self, "Prepared");
Ok(())
}
fn unprepare(&self, element: &super::ElementSrcTest) {
gst::debug!(SRC_CAT, obj: element, "Unpreparing");
fn unprepare(&self) {
gst::debug!(SRC_CAT, imp: self, "Unpreparing");
*self.sender.lock().unwrap() = None;
self.task.unprepare().block_on().unwrap();
gst::debug!(SRC_CAT, obj: element, "Unprepared");
gst::debug!(SRC_CAT, imp: self, "Unprepared");
}
fn stop(&self, element: &super::ElementSrcTest) {
gst::debug!(SRC_CAT, obj: element, "Stopping");
fn stop(&self) {
gst::debug!(SRC_CAT, imp: self, "Stopping");
self.task.stop().await_maybe_on_context().unwrap();
gst::debug!(SRC_CAT, obj: element, "Stopped");
gst::debug!(SRC_CAT, imp: self, "Stopped");
}
fn start(&self, element: &super::ElementSrcTest) {
gst::debug!(SRC_CAT, obj: element, "Starting");
fn start(&self) {
gst::debug!(SRC_CAT, imp: self, "Starting");
self.task.start().await_maybe_on_context().unwrap();
gst::debug!(SRC_CAT, obj: element, "Started");
gst::debug!(SRC_CAT, imp: self, "Started");
}
fn pause(&self, element: &super::ElementSrcTest) {
gst::debug!(SRC_CAT, obj: element, "Pausing");
fn pause(&self) {
gst::debug!(SRC_CAT, imp: self, "Pausing");
self.task.pause().block_on().unwrap();
gst::debug!(SRC_CAT, obj: element, "Paused");
gst::debug!(SRC_CAT, imp: self, "Paused");
}
}
@ -315,13 +318,7 @@ mod imp_src {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"context" => {
let context = value
@ -335,9 +332,10 @@ mod imp_src {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.src_pad.gst_pad()).unwrap();
}
}
@ -377,35 +375,34 @@ mod imp_src {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::log!(SRC_CAT, obj: element, "Changing state {:?}", transition);
gst::log!(SRC_CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare(element).map_err(|err| {
element.post_error_message(err);
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::PlayingToPaused => {
self.pause(element);
self.pause();
}
gst::StateChange::ReadyToNull => {
self.unprepare(element);
self.unprepare();
}
_ => (),
}
let mut success = self.parent_change_state(element, transition)?;
let mut success = self.parent_change_state(transition)?;
match transition {
gst::StateChange::PausedToReady => {
self.stop(element);
self.stop();
}
gst::StateChange::PausedToPlaying => {
self.start(element);
self.start();
}
gst::StateChange::ReadyToPaused | gst::StateChange::PlayingToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
@ -416,7 +413,7 @@ mod imp_src {
Ok(success)
}
fn send_event(&self, _element: &Self::Type, event: gst::Event) -> bool {
fn send_event(&self, event: gst::Event) -> bool {
match event.view() {
EventView::FlushStart(..) => {
self.task.flush_start().await_maybe_on_context().unwrap();
@ -464,9 +461,7 @@ mod imp_sink {
.unwrap();
async move {
let elem_sink_test = element.imp();
elem_sink_test
.forward_item(&element, Item::Buffer(buffer))
.await
elem_sink_test.forward_item(Item::Buffer(buffer)).await
}
.boxed()
}
@ -484,9 +479,7 @@ mod imp_sink {
.unwrap();
async move {
let elem_sink_test = element.imp();
elem_sink_test
.forward_item(&element, Item::BufferList(list))
.await
elem_sink_test.forward_item(Item::BufferList(list)).await
}
.boxed()
}
@ -495,14 +488,14 @@ mod imp_sink {
&self,
pad: &PadSinkRef,
elem_sink_test: &ElementSinkTest,
element: &gst::Element,
_element: &gst::Element,
event: gst::Event,
) -> bool {
gst::debug!(SINK_CAT, obj: pad.gst_pad(), "Handling non-serialized {:?}", event);
match event.view() {
EventView::FlushStart(..) => {
elem_sink_test.stop(element.downcast_ref::<super::ElementSinkTest>().unwrap());
elem_sink_test.stop();
true
}
_ => false,
@ -526,11 +519,11 @@ mod imp_sink {
let elem_sink_test = element.imp();
if let EventView::FlushStop(..) = event.view() {
elem_sink_test.start(&element);
elem_sink_test.start();
}
elem_sink_test
.forward_item(&element, Item::Event(event))
.forward_item(Item::Event(event))
.await
.is_ok()
}
@ -546,13 +539,9 @@ mod imp_sink {
}
impl ElementSinkTest {
async fn forward_item(
&self,
element: &super::ElementSinkTest,
item: Item,
) -> Result<gst::FlowSuccess, gst::FlowError> {
async fn forward_item(&self, item: Item) -> Result<gst::FlowSuccess, gst::FlowError> {
if !self.flushing.load(Ordering::SeqCst) {
gst::debug!(SINK_CAT, obj: element, "Fowarding {:?}", item);
gst::debug!(SINK_CAT, imp: self, "Fowarding {:?}", item);
let mut sender = self
.sender
.lock()
@ -568,7 +557,7 @@ mod imp_sink {
} else {
gst::debug!(
SINK_CAT,
obj: element,
imp: self,
"Not fowarding {:?} due to flushing",
item
);
@ -576,34 +565,32 @@ mod imp_sink {
}
}
fn start(&self, element: &super::ElementSinkTest) {
gst::debug!(SINK_CAT, obj: element, "Starting");
fn start(&self) {
gst::debug!(SINK_CAT, imp: self, "Starting");
self.flushing.store(false, Ordering::SeqCst);
gst::debug!(SINK_CAT, obj: element, "Started");
gst::debug!(SINK_CAT, imp: self, "Started");
}
fn stop(&self, element: &super::ElementSinkTest) {
gst::debug!(SINK_CAT, obj: element, "Stopping");
fn stop(&self) {
gst::debug!(SINK_CAT, imp: self, "Stopping");
self.flushing.store(true, Ordering::SeqCst);
gst::debug!(SINK_CAT, obj: element, "Stopped");
gst::debug!(SINK_CAT, imp: self, "Stopped");
}
}
impl ElementSinkTest {
pub fn push_flush_start(&self, element: &super::ElementSinkTest) {
gst::debug!(SINK_CAT, obj: element, "Pushing FlushStart");
pub fn push_flush_start(&self) {
gst::debug!(SINK_CAT, imp: self, "Pushing FlushStart");
self.sink_pad
.gst_pad()
.push_event(gst::event::FlushStart::new());
gst::debug!(SINK_CAT, obj: element, "FlushStart pushed");
gst::debug!(SINK_CAT, imp: self, "FlushStart pushed");
}
pub fn push_flush_stop(&self, element: &super::ElementSinkTest) {
gst::debug!(SINK_CAT, obj: element, "Pushing FlushStop");
pub fn push_flush_stop(&self) {
gst::debug!(SINK_CAT, imp: self, "Pushing FlushStop");
self.sink_pad
.gst_pad()
.push_event(gst::event::FlushStop::new(true));
gst::debug!(SINK_CAT, obj: element, "FlushStop pushed");
gst::debug!(SINK_CAT, imp: self, "FlushStop pushed");
}
}
@ -647,13 +634,7 @@ mod imp_sink {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"sender" => {
let ItemSender { sender } = value
@ -666,9 +647,10 @@ mod imp_sink {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.sink_pad.gst_pad()).unwrap();
}
}
@ -708,19 +690,18 @@ mod imp_sink {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::log!(SINK_CAT, obj: element, "Changing state {:?}", transition);
gst::log!(SINK_CAT, imp: self, "Changing state {:?}", transition);
if let gst::StateChange::PausedToReady = transition {
self.stop(element);
self.stop();
}
let success = self.parent_change_state(element, transition)?;
let success = self.parent_change_state(transition)?;
if let gst::StateChange::ReadyToPaused = transition {
self.start(element);
self.start();
}
Ok(success)
@ -1225,13 +1206,13 @@ fn start_flush() {
let elem_sink_test = sink_element.imp();
elem_sink_test.push_flush_start(&sink_element);
elem_sink_test.push_flush_start();
elem_src_test
.try_push(Item::Buffer(gst::Buffer::from_slice(vec![5, 6, 7])))
.unwrap_err();
elem_sink_test.push_flush_stop(&sink_element);
elem_sink_test.push_flush_stop();
elem_src_test
.try_push(Item::Event(gst::event::Segment::new(

View file

@ -8,7 +8,7 @@
use gst::glib;
use gst::prelude::*;
use gst::subclass::prelude::*;
use gst::{element_error, error_msg};
use gst::{element_imp_error, error_msg};
use serde_derive::Deserialize;
use once_cell::sync::Lazy;
@ -81,7 +81,6 @@ impl TranscribeParse {
fn sink_chain(
&self,
pad: &gst::Pad,
_element: &super::TranscribeParse,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@ -218,12 +217,7 @@ impl TranscribeParse {
Ok(())
}
fn sink_event(
&self,
pad: &gst::Pad,
element: &super::TranscribeParse,
event: gst::Event,
) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -231,14 +225,14 @@ impl TranscribeParse {
EventView::FlushStop(..) => {
let mut state = self.state.lock().unwrap();
*state = State::default();
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::Eos(..) => match self.drain() {
Ok(()) => pad.event_default(Some(element), event),
Ok(()) => pad.event_default(Some(&*self.instance()), event),
Err(err) => {
gst::error!(CAT, obj: element, "failed to drain on EOS: {}", err);
element_error!(
element,
gst::error!(CAT, imp: self, "failed to drain on EOS: {}", err);
element_imp_error!(
self,
gst::StreamError::Failed,
["Streaming failed: {}", err]
);
@ -247,7 +241,7 @@ impl TranscribeParse {
}
},
EventView::Segment(..) | EventView::Caps(..) => true,
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
}
@ -265,14 +259,14 @@ impl ObjectSubclass for TranscribeParse {
TranscribeParse::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|parse, element| parse.sink_chain(pad, element, buffer),
|parse| parse.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
TranscribeParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.sink_event(pad, element, event),
|parse| parse.sink_event(pad, event),
)
})
.build();
@ -289,9 +283,10 @@ impl ObjectSubclass for TranscribeParse {
}
impl ObjectImpl for TranscribeParse {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -343,10 +338,9 @@ impl ElementImpl for TranscribeParse {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused | gst::StateChange::PausedToReady => {
@ -357,6 +351,6 @@ impl ElementImpl for TranscribeParse {
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -9,7 +9,7 @@
use gst::glib;
use gst::prelude::*;
use gst::subclass::prelude::*;
use gst::{element_error, error_msg, loggable_error};
use gst::{element_imp_error, error_msg, loggable_error};
use std::default::Default;
@ -219,11 +219,11 @@ fn build_packet(payload: &[u8]) -> Vec<u8> {
}
impl Transcriber {
fn dequeue(&self, element: &super::Transcriber) -> bool {
fn dequeue(&self) -> bool {
/* First, check our pending buffers */
let mut items = vec![];
let now = match element.current_running_time() {
let now = match self.instance().current_running_time() {
Some(now) => now,
None => {
return true;
@ -248,7 +248,7 @@ impl Transcriber {
let pts = buf.pts().unwrap();
gst::trace!(
CAT,
obj: element,
imp: self,
"Checking now {} if item is ready for dequeuing, PTS {}, threshold {} vs {}",
now,
pts,
@ -305,7 +305,7 @@ impl Transcriber {
gst::warning!(
CAT,
obj: element,
imp: self,
"Updating item PTS ({} < {}), consider increasing latency",
pts,
last_position
@ -336,7 +336,7 @@ impl Transcriber {
/* next, push a gap if we're lagging behind the target position */
gst::trace!(
CAT,
obj: element,
imp: self,
"Checking now: {} if we need to push a gap, last_position: {}, threshold: {}",
now,
last_position,
@ -374,19 +374,13 @@ impl Transcriber {
true
}
fn enqueue(
&self,
element: &super::Transcriber,
state: &mut State,
alternative: &TranscriptAlternative,
partial: bool,
) {
fn enqueue(&self, state: &mut State, alternative: &TranscriptAlternative, partial: bool) {
let lateness = self.settings.lock().unwrap().lateness;
if alternative.items.len() <= state.partial_index {
gst::error!(
CAT,
obj: element,
imp: self,
"sanity check failed, alternative length {} < partial_index {}",
alternative.items.len(),
state.partial_index
@ -414,7 +408,7 @@ impl Transcriber {
/* Should be sent now */
gst::debug!(
CAT,
obj: element,
imp: self,
"Item is ready for queuing: {}, PTS {}",
item.content,
start_time
@ -443,11 +437,7 @@ impl Transcriber {
}
}
fn loop_fn(
&self,
element: &super::Transcriber,
receiver: &mut mpsc::Receiver<Message>,
) -> Result<(), gst::ErrorMessage> {
fn loop_fn(&self, receiver: &mut mpsc::Receiver<Message>) -> Result<(), gst::ErrorMessage> {
let mut events = {
let mut events = vec![];
@ -482,7 +472,7 @@ impl Transcriber {
};
for event in events.drain(..) {
gst::info!(CAT, obj: element, "Sending {:?}", event);
gst::info!(CAT, imp: self, "Sending {:?}", event);
self.srcpad.push_event(event);
}
@ -499,7 +489,7 @@ impl Transcriber {
match msg {
Message::Binary(buf) => {
let (_, pkt) = parse_packet(&buf).map_err(|err| {
gst::error!(CAT, obj: element, "Failed to parse packet: {}", err);
gst::error!(CAT, imp: self, "Failed to parse packet: {}", err);
error_msg!(
gst::StreamError::Failed,
["Failed to parse packet: {}", err]
@ -513,7 +503,7 @@ impl Transcriber {
serde_json::from_str(payload).map_err(|err| {
gst::error!(
CAT,
obj: element,
imp: self,
"Unexpected exception message: {} ({})",
payload,
err
@ -523,12 +513,7 @@ impl Transcriber {
["Unexpected exception message: {} ({})", payload, err]
)
})?;
gst::error!(
CAT,
obj: element,
"AWS raised an error: {}",
message.message
);
gst::error!(CAT, imp: self, "AWS raised an error: {}", message.message);
return Err(error_msg!(
gst::StreamError::Failed,
@ -546,7 +531,7 @@ impl Transcriber {
if let Some(result) = transcript.transcript.results.get(0) {
gst::trace!(
CAT,
obj: element,
imp: self,
"result: {}",
serde_json::to_string_pretty(&result).unwrap(),
);
@ -554,7 +539,7 @@ impl Transcriber {
if let Some(alternative) = result.alternatives.get(0) {
let mut state = self.state.lock().unwrap();
self.enqueue(element, &mut state, alternative, result.is_partial)
self.enqueue(&mut state, alternative, result.is_partial)
}
}
@ -569,16 +554,16 @@ impl Transcriber {
let future = async move {
match tokio::time::timeout(GRANULARITY.into(), future).await {
Err(_) => {
if !self.dequeue(element) {
gst::info!(CAT, obj: element, "Failed to push gap event, pausing");
if !self.dequeue() {
gst::info!(CAT, imp: self, "Failed to push gap event, pausing");
let _ = self.srcpad.pause_task();
}
Ok(())
}
Ok(res) => {
if !self.dequeue(element) {
gst::info!(CAT, obj: element, "Failed to push gap event, pausing");
if !self.dequeue() {
gst::info!(CAT, imp: self, "Failed to push gap event, pausing");
let _ = self.srcpad.pause_task();
}
@ -591,9 +576,7 @@ impl Transcriber {
futures::executor::block_on(future)
}
fn start_task(&self, element: &super::Transcriber) -> Result<(), gst::LoggableError> {
let element_weak = element.downgrade();
let pad_weak = self.srcpad.downgrade();
fn start_task(&self) -> Result<(), gst::LoggableError> {
let (sender, mut receiver) = mpsc::channel(1);
{
@ -601,25 +584,11 @@ impl Transcriber {
state.sender = Some(sender);
}
let imp = self.ref_counted();
let res = self.srcpad.start_task(move || {
let element = match element_weak.upgrade() {
Some(element) => element,
None => {
if let Some(pad) = pad_weak.upgrade() {
let _ = pad.pause_task();
}
return;
}
};
let transcribe = element.imp();
if let Err(err) = transcribe.loop_fn(&element, &mut receiver) {
element_error!(
&element,
gst::StreamError::Failed,
["Streaming failed: {}", err]
);
let _ = transcribe.srcpad.pause_task();
if let Err(err) = imp.loop_fn(&mut receiver) {
element_imp_error!(imp, gst::StreamError::Failed, ["Streaming failed: {}", err]);
let _ = imp.srcpad.pause_task();
}
});
if res.is_err() {
@ -631,12 +600,11 @@ impl Transcriber {
fn src_activatemode(
&self,
_pad: &gst::Pad,
element: &super::Transcriber,
_mode: gst::PadMode,
active: bool,
) -> Result<(), gst::LoggableError> {
if active {
self.start_task(element)?;
self.start_task()?;
} else {
{
let mut state = self.state.lock().unwrap();
@ -649,12 +617,7 @@ impl Transcriber {
Ok(())
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::Transcriber,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
@ -685,17 +648,17 @@ impl Transcriber {
false
}
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
fn sink_event(&self, pad: &gst::Pad, element: &super::Transcriber, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() {
EventView::Eos(_) => match self.handle_buffer(pad, element, None) {
EventView::Eos(_) => match self.handle_buffer(pad, None) {
Err(err) => {
gst::error!(CAT, "Failed to send EOS to AWS: {}", err);
false
@ -703,31 +666,31 @@ impl Transcriber {
Ok(_) => true,
},
EventView::FlushStart(_) => {
gst::info!(CAT, obj: element, "Received flush start, disconnecting");
let mut ret = pad.event_default(Some(element), event);
gst::info!(CAT, imp: self, "Received flush start, disconnecting");
let mut ret = pad.event_default(Some(&*self.instance()), event);
match self.srcpad.stop_task() {
Err(err) => {
gst::error!(CAT, obj: element, "Failed to stop srcpad task: {}", err);
gst::error!(CAT, imp: self, "Failed to stop srcpad task: {}", err);
self.disconnect(element);
self.disconnect();
ret = false;
}
Ok(_) => {
self.disconnect(element);
self.disconnect();
}
};
ret
}
EventView::FlushStop(_) => {
gst::info!(CAT, obj: element, "Received flush stop, restarting task");
gst::info!(CAT, imp: self, "Received flush stop, restarting task");
if pad.event_default(Some(element), event) {
match self.start_task(element) {
if pad.event_default(Some(&*self.instance()), event) {
match self.start_task() {
Err(err) => {
gst::error!(CAT, obj: element, "Failed to start srcpad task: {}", err);
gst::error!(CAT, imp: self, "Failed to start srcpad task: {}", err);
false
}
Ok(_) => true,
@ -739,8 +702,8 @@ impl Transcriber {
EventView::Segment(e) => {
let segment = match e.segment().clone().downcast::<gst::ClockTime>() {
Err(segment) => {
element_error!(
element,
element_imp_error!(
self,
gst::StreamError::Format,
["Only Time segments supported, got {:?}", segment.format(),]
);
@ -762,13 +725,12 @@ impl Transcriber {
true
}
EventView::StreamStart(_) => true,
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
async fn sync_and_send(
&self,
element: &super::Transcriber,
buffer: Option<gst::Buffer>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut delay = None;
@ -778,7 +740,7 @@ impl Transcriber {
if let Some(buffer) = &buffer {
let running_time = state.in_segment.to_running_time(buffer.pts());
let now = element.current_running_time();
let now = self.instance().current_running_time();
delay = running_time.opt_checked_sub(now).ok().flatten();
}
@ -794,7 +756,7 @@ impl Transcriber {
for chunk in data.chunks(8192) {
let packet = build_packet(chunk);
ws_sink.send(Message::Binary(packet)).await.map_err(|err| {
gst::error!(CAT, obj: element, "Failed sending packet: {}", err);
gst::error!(CAT, imp: self, "Failed sending packet: {}", err);
gst::FlowError::Error
})?;
}
@ -802,7 +764,7 @@ impl Transcriber {
// EOS
let packet = build_packet(&[]);
ws_sink.send(Message::Binary(packet)).await.map_err(|err| {
gst::error!(CAT, obj: element, "Failed sending packet: {}", err);
gst::error!(CAT, imp: self, "Failed sending packet: {}", err);
gst::FlowError::Error
})?;
}
@ -814,21 +776,20 @@ impl Transcriber {
fn handle_buffer(
&self,
_pad: &gst::Pad,
element: &super::Transcriber,
buffer: Option<gst::Buffer>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: element, "Handling {:?}", buffer);
gst::log!(CAT, imp: self, "Handling {:?}", buffer);
self.ensure_connection(element).map_err(|err| {
element_error!(
element,
self.ensure_connection().map_err(|err| {
element_imp_error!(
self,
gst::StreamError::Failed,
["Streaming failed: {}", err]
);
gst::FlowError::Error
})?;
let (future, abort_handle) = abortable(self.sync_and_send(element, buffer));
let (future, abort_handle) = abortable(self.sync_and_send(buffer));
self.state.lock().unwrap().send_abort_handle = Some(abort_handle);
@ -846,13 +807,12 @@ impl Transcriber {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::Transcriber,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
self.handle_buffer(pad, element, Some(buffer))
self.handle_buffer(pad, Some(buffer))
}
fn ensure_connection(&self, element: &super::Transcriber) -> Result<(), gst::ErrorMessage> {
fn ensure_connection(&self) -> Result<(), gst::ErrorMessage> {
let state = self.state.lock().unwrap();
if state.connected {
@ -868,7 +828,7 @@ impl Transcriber {
if settings.latency + settings.lateness <= 2 * GRANULARITY {
gst::error!(
CAT,
obj: element,
imp: self,
"latency + lateness must be greater than 200 milliseconds"
);
return Err(error_msg!(
@ -877,7 +837,7 @@ impl Transcriber {
));
}
gst::info!(CAT, obj: element, "Connecting ..");
gst::info!(CAT, imp: self, "Connecting ..");
let region = Region::new(DEFAULT_TRANSCRIBER_REGION);
let access_key = settings.access_key.as_ref();
@ -888,7 +848,7 @@ impl Transcriber {
(Some(key), Some(secret_key)) => {
gst::debug!(
CAT,
obj: element,
imp: self,
"Using provided access and secret access key"
);
Ok(Credentials::new(
@ -900,7 +860,7 @@ impl Transcriber {
))
}
_ => {
gst::debug!(CAT, obj: element, "Using default AWS credentials");
gst::debug!(CAT, imp: self, "Using default AWS credentials");
let cred_future = async {
let cred = DefaultCredentialsChain::builder()
.region(region.clone())
@ -960,7 +920,7 @@ impl Transcriber {
}
if let Some(ref session_id) = settings.session_id {
gst::debug!(CAT, obj: element, "Using session ID: {}", session_id);
gst::debug!(CAT, imp: self, "Using session ID: {}", session_id);
query_params.push_str(format!("&session-id={}", session_id).as_str());
}
@ -998,12 +958,7 @@ impl Transcriber {
.path_and_query(query_params.clone())
.build()
.map_err(|err| {
gst::error!(
CAT,
obj: element,
"Failed to build HTTP request URI: {}",
err
);
gst::error!(CAT, imp: self, "Failed to build HTTP request URI: {}", err);
error_msg!(
gst::CoreError::Failed,
["Failed to build HTTP request URI: {}", err]
@ -1021,7 +976,7 @@ impl Transcriber {
&mut request,
)
.map_err(|err| {
gst::error!(CAT, obj: element, "Failed to sign HTTP request: {}", err);
gst::error!(CAT, imp: self, "Failed to sign HTTP request: {}", err);
error_msg!(
gst::CoreError::Failed,
["Failed to sign HTTP request: {}", err]
@ -1033,7 +988,7 @@ impl Transcriber {
let _enter = RUNTIME.enter();
futures::executor::block_on(connect_async(format!("wss{}", &url[5..]))).map_err(
|err| {
gst::error!(CAT, obj: element, "Failed to connect: {}", err);
gst::error!(CAT, imp: self, "Failed to connect: {}", err);
error_msg!(gst::CoreError::Failed, ["Failed to connect: {}", err])
},
)?
@ -1043,10 +998,9 @@ impl Transcriber {
*self.ws_sink.borrow_mut() = Some(Box::pin(ws_sink));
let element_weak = element.downgrade();
let imp_weak = self.downgrade();
let future = async move {
while let Some(element) = element_weak.upgrade() {
let transcribe = element.imp();
while let Some(transcribe) = imp_weak.upgrade() {
let msg = match ws_stream.next().await {
Some(msg) => msg,
None => {
@ -1059,9 +1013,9 @@ impl Transcriber {
let msg = match msg {
Ok(msg) => msg,
Err(err) => {
gst::error!(CAT, "Failed to receive data: {}", err);
element_error!(
element,
gst::error!(CAT, imp: transcribe, "Failed to receive data: {}", err);
element_imp_error!(
transcribe,
gst::StreamError::Failed,
["Streaming failed: {}", err]
);
@ -1089,15 +1043,15 @@ impl Transcriber {
state.connected = true;
gst::info!(CAT, obj: element, "Connected");
gst::info!(CAT, imp: self, "Connected");
Ok(())
}
fn disconnect(&self, element: &super::Transcriber) {
fn disconnect(&self) {
let mut state = self.state.lock().unwrap();
gst::info!(CAT, obj: element, "Unpreparing");
gst::info!(CAT, imp: self, "Unpreparing");
if let Some(abort_handle) = state.recv_abort_handle.take() {
abort_handle.abort();
@ -1111,7 +1065,7 @@ impl Transcriber {
gst::info!(
CAT,
obj: element,
imp: self,
"Unprepared, connected: {}!",
state.connected
);
@ -1131,14 +1085,14 @@ impl ObjectSubclass for Transcriber {
Transcriber::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|transcriber, element| transcriber.sink_chain(pad, element, buffer),
|transcriber| transcriber.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
Transcriber::catch_panic_pad_function(
parent,
|| false,
|transcriber, element| transcriber.sink_event(pad, element, event),
|transcriber| transcriber.sink_event(pad, event),
)
})
.build();
@ -1149,14 +1103,14 @@ impl ObjectSubclass for Transcriber {
Transcriber::catch_panic_pad_function(
parent,
|| Err(loggable_error!(CAT, "Panic activating src pad with mode")),
|transcriber, element| transcriber.src_activatemode(pad, element, mode, active),
|transcriber| transcriber.src_activatemode(pad, mode, active),
)
})
.query_function(|pad, parent, query| {
Transcriber::catch_panic_pad_function(
parent,
|| false,
|transcriber, element| transcriber.src_query(pad, element, query),
|transcriber| transcriber.src_query(pad, query),
)
})
.flags(gst::PadFlags::FIXED_CAPS)
@ -1248,21 +1202,16 @@ impl ObjectImpl for Transcriber {
PROPERTIES.as_ref()
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
obj.set_element_flags(gst::ElementFlags::PROVIDE_CLOCK | gst::ElementFlags::REQUIRE_CLOCK);
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"language-code" => {
let mut settings = self.settings.lock().unwrap();
@ -1320,7 +1269,7 @@ impl ObjectImpl for Transcriber {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"language-code" => {
let settings = self.settings.lock().unwrap();
@ -1421,16 +1370,15 @@ impl ElementImpl for Transcriber {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::info!(CAT, obj: element, "Changing state {:?}", transition);
gst::info!(CAT, imp: self, "Changing state {:?}", transition);
let mut success = self.parent_change_state(element, transition)?;
let mut success = self.parent_change_state(transition)?;
match transition {
gst::StateChange::PausedToReady => {
self.disconnect(element);
self.disconnect();
}
gst::StateChange::ReadyToPaused => {
success = gst::StateChangeSuccess::NoPreroll;
@ -1444,7 +1392,7 @@ impl ElementImpl for Transcriber {
Ok(success)
}
fn provide_clock(&self, _element: &Self::Type) -> Option<gst::Clock> {
fn provide_clock(&self) -> Option<gst::Clock> {
Some(gst::SystemClock::obtain())
}
}

View file

@ -17,8 +17,7 @@ use std::sync::Mutex;
use std::thread::{spawn, JoinHandle};
use std::time::Duration;
use gio::prelude::{Cast, ToValue};
use gst::{element_error, glib, prelude::ObjectExt, prelude::*, subclass::prelude::*};
use gst::{element_imp_error, glib, prelude::*, subclass::prelude::*};
use aws_sdk_s3::config;
use aws_sdk_s3::model::ObjectCannedAcl;
@ -217,190 +216,186 @@ impl Drop for S3Upload {
}
}
fn s3_request(element: super::S3HlsSink, rxc: Receiver<S3RequestControl>, rx: Receiver<S3Request>) {
let bin = element.imp();
loop {
match rxc.try_recv() {
Ok(S3RequestControl::Continue) => (),
Ok(S3RequestControl::Pause) => {
gst::debug!(CAT, obj: &element, "Pausing S3 request thread.");
match rxc.recv() {
Ok(S3RequestControl::Continue) => {
gst::debug!(CAT, obj: &element, "Continuing S3 request thread.")
impl S3HlsSink {
fn s3_request(&self, rxc: Receiver<S3RequestControl>, rx: Receiver<S3Request>) {
loop {
match rxc.try_recv() {
Ok(S3RequestControl::Continue) => (),
Ok(S3RequestControl::Pause) => {
gst::debug!(CAT, imp: self, "Pausing S3 request thread.");
match rxc.recv() {
Ok(S3RequestControl::Continue) => {
gst::debug!(CAT, imp: self, "Continuing S3 request thread.")
}
// We do not expect another pause request here.
Ok(S3RequestControl::Pause) => unreachable!(),
Err(_) => (),
}
// We do not expect another pause request here.
Ok(S3RequestControl::Pause) => unreachable!(),
Err(_) => (),
}
/*
* We are not concerned with `Empty` and since we close the control
* channel ourselves when required, `Disconnected` will be expected.
*/
Err(_) => (),
};
match rx.recv() {
Ok(S3Request::Upload(data)) => {
let s3_client = data.s3_client.clone();
let s3_bucket = data.s3_bucket.clone();
let s3_key = data.s3_key.clone();
let s3_acl = data.s3_acl;
let s3_data_len = data.s3_data.len();
gst::debug!(CAT, imp: self, "Uploading key {}", s3_key);
let put_object_req = s3_client
.put_object()
.set_bucket(Some(s3_bucket))
.set_key(Some(s3_key.clone()))
.set_body(Some(ByteStream::from(data.s3_data)))
.set_acl(Some(s3_acl));
let put_object_req_future = put_object_req.send();
let result = s3utils::wait(&self.canceller, put_object_req_future);
if let Err(err) = result {
gst::error!(
CAT,
imp: self,
"Put object request for S3 key {} of data length {} failed with error {:?}",
s3_key,
s3_data_len,
err,
);
element_imp_error!(
self,
gst::ResourceError::Write,
["Put object request failed"]
);
break;
};
}
Ok(S3Request::Delete(data)) => {
let s3_client = data.s3_client.clone();
let s3_bucket = data.s3_bucket.clone();
let s3_key = data.s3_key.clone();
gst::debug!(CAT, imp: self, "Deleting key {}", s3_key);
let delete_object_req = s3_client
.delete_object()
.set_bucket(Some(s3_bucket))
.set_key(Some(s3_key.clone()));
let delete_object_req_future = delete_object_req.send();
let result = s3utils::wait(&self.canceller, delete_object_req_future);
if let Err(err) = result {
gst::error!(
CAT,
imp: self,
"Delete object request for S3 key {} failed with error {:?}",
s3_key,
err
);
element_imp_error!(
self,
gst::ResourceError::Write,
["Delete object request failed"]
);
break;
};
}
Ok(S3Request::Stop) => break,
Err(err) => {
gst::error!(CAT, imp: self, "S3 channel error: {}", err);
element_imp_error!(self, gst::ResourceError::Write, ["S3 channel error"]);
break;
}
}
/*
* We are not concerned with `Empty` and since we close the control
* channel ourselves when required, `Disconnected` will be expected.
*/
Err(_) => (),
};
match rx.recv() {
Ok(S3Request::Upload(data)) => {
let s3_client = data.s3_client.clone();
let s3_bucket = data.s3_bucket.clone();
let s3_key = data.s3_key.clone();
let s3_acl = data.s3_acl;
let s3_data_len = data.s3_data.len();
gst::debug!(CAT, obj: &element, "Uploading key {}", s3_key);
let put_object_req = s3_client
.put_object()
.set_bucket(Some(s3_bucket))
.set_key(Some(s3_key.clone()))
.set_body(Some(ByteStream::from(data.s3_data)))
.set_acl(Some(s3_acl));
let put_object_req_future = put_object_req.send();
let result = s3utils::wait(&bin.canceller, put_object_req_future);
if let Err(err) = result {
gst::error!(
CAT,
obj: &element,
"Put object request for S3 key {} of data length {} failed with error {:?}",
s3_key,
s3_data_len,
err,
);
element_error!(
element,
gst::ResourceError::Write,
["Put object request failed"]
);
break;
};
}
Ok(S3Request::Delete(data)) => {
let s3_client = data.s3_client.clone();
let s3_bucket = data.s3_bucket.clone();
let s3_key = data.s3_key.clone();
gst::debug!(CAT, obj: &element, "Deleting key {}", s3_key);
let delete_object_req = s3_client
.delete_object()
.set_bucket(Some(s3_bucket))
.set_key(Some(s3_key.clone()));
let delete_object_req_future = delete_object_req.send();
let result = s3utils::wait(&bin.canceller, delete_object_req_future);
if let Err(err) = result {
gst::error!(
CAT,
obj: &element,
"Delete object request for S3 key {} failed with error {:?}",
s3_key,
err
);
element_error!(
element,
gst::ResourceError::Write,
["Delete object request failed"]
);
break;
};
}
Ok(S3Request::Stop) => break,
Err(err) => {
gst::error!(CAT, obj: &element, "S3 channel error: {}", err);
element_error!(element, gst::ResourceError::Write, ["S3 channel error"]);
break;
}
}
gst::info!(CAT, imp: self, "Exiting S3 request thread",);
}
gst::info!(CAT, obj: &element, "Exiting S3 request thread",);
}
fn s3client_from_settings(&self) -> Client {
let mut settings = self.settings.lock().unwrap();
fn s3client_from_settings(element: &super::S3HlsSink) -> Client {
let bin = element.imp();
let mut settings = bin.settings.lock().unwrap();
if settings.config.is_none() {
let timeout_config = s3utils::timeout_config(settings.request_timeout);
let access_key = settings.access_key.as_ref();
let secret_access_key = settings.secret_access_key.as_ref();
let session_token = settings.session_token.clone();
if settings.config.is_none() {
let timeout_config = s3utils::timeout_config(settings.request_timeout);
let access_key = settings.access_key.as_ref();
let secret_access_key = settings.secret_access_key.as_ref();
let session_token = settings.session_token.clone();
let cred = match (access_key, secret_access_key) {
(Some(access), Some(secret_access)) => Some(Credentials::new(
access,
secret_access,
session_token,
None,
"s3-hlssink",
)),
_ => None,
};
let cred = match (access_key, secret_access_key) {
(Some(access), Some(secret_access)) => Some(Credentials::new(
access,
secret_access,
session_token,
None,
"s3-hlssink",
)),
_ => None,
let sdk_config = s3utils::wait_config(
&self.canceller,
settings.s3_region.clone(),
timeout_config,
cred,
)
.expect("Failed to get SDK config");
settings.config = Some(sdk_config);
}
let sdk_config = settings.config.as_ref().expect("SDK config must be set");
let endpoint_uri = match &settings.endpoint_uri {
Some(endpoint) => match endpoint.parse::<Uri>() {
Ok(uri) => Some(uri),
Err(e) => {
element_imp_error!(
self,
gst::ResourceError::Settings,
["Invalid S3 endpoint uri. Error: {}", e]
);
None
}
},
None => None,
};
let sdk_config = s3utils::wait_config(
&bin.canceller,
settings.s3_region.clone(),
timeout_config,
cred,
)
.expect("Failed to get SDK config");
let config_builder = config::Builder::from(sdk_config)
.region(settings.s3_region.clone())
.retry_config(RetryConfig::standard().with_max_attempts(settings.retry_attempts));
settings.config = Some(sdk_config);
let config = if let Some(uri) = endpoint_uri {
config_builder
.endpoint_resolver(Endpoint::mutable(uri))
.build()
} else {
config_builder.build()
};
Client::from_conf(config)
}
let sdk_config = settings.config.as_ref().expect("SDK config must be set");
let endpoint_uri = match &settings.endpoint_uri {
Some(endpoint) => match endpoint.parse::<Uri>() {
Ok(uri) => Some(uri),
Err(e) => {
element_error!(
element,
gst::ResourceError::Settings,
["Invalid S3 endpoint uri. Error: {}", e]
);
None
}
},
None => None,
};
let config_builder = config::Builder::from(sdk_config)
.region(settings.s3_region.clone())
.retry_config(RetryConfig::standard().with_max_attempts(settings.retry_attempts));
let config = if let Some(uri) = endpoint_uri {
config_builder
.endpoint_resolver(Endpoint::mutable(uri))
.build()
} else {
config_builder.build()
};
Client::from_conf(config)
}
impl S3HlsSink {
fn stop(&self) {
let bin = self.instance();
let mut settings = self.settings.lock().unwrap();
let s3_handle = settings.s3_upload_handle.take();
let s3_tx = settings.s3_tx.clone();
if let (Some(handle), Some(tx)) = (s3_handle, s3_tx) {
gst::info!(CAT, obj: &bin, "Stopping S3 request thread");
gst::info!(CAT, imp: self, "Stopping S3 request thread");
match tx.send(S3Request::Stop) {
Ok(_) => {
gst::info!(CAT, obj: &bin, "Joining S3 request thread");
gst::info!(CAT, imp: self, "Joining S3 request thread");
if let Err(err) = handle.join() {
gst::error!(CAT, obj: &bin, "S3 upload thread failed to exit: {:?}", err);
gst::error!(CAT, imp: self, "S3 upload thread failed to exit: {:?}", err);
}
drop(tx);
}
Err(err) => {
gst::error!(CAT, obj: &bin, "Failed to stop S3 request thread: {}", err)
gst::error!(CAT, imp: self, "Failed to stop S3 request thread: {}", err)
}
};
};
@ -499,18 +494,12 @@ impl ObjectImpl for S3HlsSink {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
gst::debug!(
CAT,
obj: obj,
imp: self,
"Setting property '{}' to '{:?}'",
pspec.name(),
value
@ -560,7 +549,7 @@ impl ObjectImpl for S3HlsSink {
}
}
fn property(&self, _: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
@ -579,10 +568,10 @@ impl ObjectImpl for S3HlsSink {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
obj.add(&self.hlssink).unwrap();
self.instance().add(&self.hlssink).unwrap();
let mut settings = self.settings.lock().unwrap();
@ -595,28 +584,27 @@ impl ObjectImpl for S3HlsSink {
let playlist_tx = tx.clone();
let fragment_tx = tx.clone();
let delete_tx = tx;
let element = obj.clone();
let handle = spawn(move || s3_request(element, rxc, rx));
let self_ = self.ref_counted();
let handle = spawn(move || self_.s3_request(rxc, rx));
settings.s3_upload_handle = Some(handle);
settings.s3_tx = Some(s3_tx);
settings.s3_txc = Some(txc);
drop(settings);
gst::info!(CAT, obj: obj, "Constructed");
gst::info!(CAT, imp: self, "Constructed");
self.hlssink.connect("get-playlist-stream", false, {
let element_weak = obj.downgrade();
let self_weak = self.downgrade();
move |args| -> Option<glib::Value> {
let element = match element_weak.upgrade() {
Some(element) => element,
let self_ = match self_weak.upgrade() {
Some(self_) => self_,
None => return None,
};
let s3hlssink = element.imp();
let s3client = s3client_from_settings(&element);
let settings = s3hlssink.settings.lock().unwrap();
let s3client = self_.s3client_from_settings();
let settings = self_.settings.lock().unwrap();
let s3_location = args[1].get::<&str>().unwrap();
let upload = S3Upload::new(
@ -626,7 +614,7 @@ impl ObjectImpl for S3HlsSink {
playlist_tx.clone(),
);
gst::debug!(CAT, obj: &element, "New upload for {}", s3_location);
gst::debug!(CAT, imp: self_, "New upload for {}", s3_location);
Some(
gio::WriteOutputStream::new(upload)
@ -637,16 +625,15 @@ impl ObjectImpl for S3HlsSink {
});
self.hlssink.connect("get-fragment-stream", false, {
let element_weak = obj.downgrade();
let self_weak = self.downgrade();
move |args| -> Option<glib::Value> {
let element = match element_weak.upgrade() {
Some(element) => element,
let self_ = match self_weak.upgrade() {
Some(self_) => self_,
None => return None,
};
let s3hlssink = element.imp();
let s3client = s3client_from_settings(&element);
let settings = s3hlssink.settings.lock().unwrap();
let s3client = self_.s3client_from_settings();
let settings = self_.settings.lock().unwrap();
let s3_location = args[1].get::<&str>().unwrap();
let upload = S3Upload::new(
@ -656,7 +643,7 @@ impl ObjectImpl for S3HlsSink {
fragment_tx.clone(),
);
gst::debug!(CAT, obj: &element, "New upload for {}", s3_location);
gst::debug!(CAT, imp: self_, "New upload for {}", s3_location);
Some(
gio::WriteOutputStream::new(upload)
@ -667,17 +654,16 @@ impl ObjectImpl for S3HlsSink {
});
self.hlssink.connect("delete-fragment", false, {
let element_weak = obj.downgrade();
move |args| {
let element = match element_weak.upgrade() {
Some(element) => element,
let self_weak = self.downgrade();
move |args| -> Option<glib::Value> {
let self_ = match self_weak.upgrade() {
Some(self_) => self_,
None => return None,
};
let s3hlssink = element.imp();
let s3_client = s3client_from_settings(&element);
let s3_client = self_.s3client_from_settings();
let settings = self_.settings.lock().unwrap();
let settings = s3hlssink.settings.lock().unwrap();
let s3_bucket = settings.s3_bucket.as_ref().unwrap().clone();
let s3_location = args[1].get::<String>().unwrap();
@ -688,7 +674,7 @@ impl ObjectImpl for S3HlsSink {
s3_location.to_string()
};
gst::debug!(CAT, obj: &element, "Deleting {}", s3_location);
gst::debug!(CAT, imp: self_, "Deleting {}", s3_location);
let delete = S3DeleteReq {
s3_client,
@ -700,13 +686,13 @@ impl ObjectImpl for S3HlsSink {
// The signature on delete-fragment signal is different for
// hlssink2 and hlssink3.
if s3hlssink.hlssink.name().contains("hlssink3") {
if self_.hlssink.name().contains("hlssink3") {
if res.is_ok() {
Some(true.to_value())
} else {
gst::error!(CAT, obj: &element, "Failed deleting {}", s3_location);
element_error!(
element,
gst::error!(CAT, imp: self_, "Failed deleting {}", s3_location);
element_imp_error!(
self_,
gst::ResourceError::Write,
["Failed to delete fragment"]
);
@ -764,10 +750,9 @@ impl ElementImpl for S3HlsSink {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
let ret = self.parent_change_state(element, transition)?;
let ret = self.parent_change_state(transition)?;
/*
* The settings lock must not be taken before the parent state change.
* Parent state change will result in the callback getting called which
@ -781,13 +766,13 @@ impl ElementImpl for S3HlsSink {
if let Some(tx) = s3_txc {
gst::debug!(
CAT,
obj: element,
imp: self,
"Sending pause request to S3 request thread."
);
if settings.s3_upload_handle.is_some()
&& tx.send(S3RequestControl::Pause).is_err()
{
gst::error!(CAT, obj: element, "Could not send pause request.");
gst::error!(CAT, imp: self, "Could not send pause request.");
}
}
}
@ -796,11 +781,11 @@ impl ElementImpl for S3HlsSink {
if let Some(tx) = s3_txc {
gst::debug!(
CAT,
obj: element,
imp: self,
"Sending continue request to S3 request thread."
);
if tx.send(S3RequestControl::Continue).is_err() {
gst::error!(CAT, obj: element, "Could not send continue request.");
gst::error!(CAT, imp: self, "Could not send continue request.");
}
}
}
@ -820,7 +805,6 @@ impl ElementImpl for S3HlsSink {
fn request_new_pad(
&self,
element: &Self::Type,
templ: &gst::PadTemplate,
_name: Option<String>,
_caps: Option<&gst::Caps>,
@ -831,7 +815,7 @@ impl ElementImpl for S3HlsSink {
if settings.audio_sink {
gst::debug!(
CAT,
obj: element,
imp: self,
"requested_new_pad: audio pad is already set"
);
return None;
@ -841,7 +825,7 @@ impl ElementImpl for S3HlsSink {
let sink_pad =
gst::GhostPad::from_template_with_target(templ, Some("audio"), &audio_pad)
.unwrap();
element.add_pad(&sink_pad).unwrap();
self.instance().add_pad(&sink_pad).unwrap();
sink_pad.set_active(true).unwrap();
settings.audio_sink = true;
@ -851,7 +835,7 @@ impl ElementImpl for S3HlsSink {
if settings.video_sink {
gst::debug!(
CAT,
obj: element,
imp: self,
"requested_new_pad: video pad is already set"
);
return None;
@ -861,14 +845,14 @@ impl ElementImpl for S3HlsSink {
let sink_pad =
gst::GhostPad::from_template_with_target(templ, Some("video"), &video_pad)
.unwrap();
element.add_pad(&sink_pad).unwrap();
self.instance().add_pad(&sink_pad).unwrap();
sink_pad.set_active(true).unwrap();
settings.video_sink = true;
Some(sink_pad.upcast())
}
_ => {
gst::debug!(CAT, obj: element, "requested_new_pad is not audio or video");
gst::debug!(CAT, imp: self, "requested_new_pad is not audio or video");
None
}
}
@ -876,7 +860,7 @@ impl ElementImpl for S3HlsSink {
}
impl BinImpl for S3HlsSink {
fn handle_message(&self, bin: &Self::Type, message: gst::Message) {
fn handle_message(&self, message: gst::Message) {
use gst::MessageView;
match message.view() {
MessageView::Eos(_) | MessageView::Error(_) => {
@ -890,13 +874,13 @@ impl BinImpl for S3HlsSink {
* unblock the S3 request thread from waiting for a Continue request
* on the control channel.
*/
gst::debug!(CAT, obj: bin, "Got EOS, dropping control channel");
gst::debug!(CAT, imp: self, "Got EOS, dropping control channel");
drop(txc);
}
drop(settings);
self.parent_handle_message(bin, message)
self.parent_handle_message(message)
}
_ => self.parent_handle_message(bin, message),
_ => self.parent_handle_message(message),
}
}
}

View file

@ -123,18 +123,18 @@ impl Settings {
)
}
fn to_metadata(&self, element: &super::S3Sink) -> Option<HashMap<String, String>> {
fn to_metadata(&self, imp: &S3Sink) -> Option<HashMap<String, String>> {
self.metadata.as_ref().map(|structure| {
let mut hash = HashMap::new();
for (key, value) in structure.iter() {
if let Ok(Ok(value_str)) = value.transform::<String>().map(|v| v.get()) {
gst::log!(CAT, obj: element, "metadata '{}' -> '{}'", key, value_str);
gst::log!(CAT, imp: imp, "metadata '{}' -> '{}'", key, value_str);
hash.insert(key.to_string(), value_str);
} else {
gst::warning!(
CAT,
obj: element,
imp: imp,
"Failed to convert metadata '{}' to string ('{:?}')",
key,
value
@ -185,10 +185,7 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
impl S3Sink {
fn flush_current_buffer(
&self,
element: &super::S3Sink,
) -> Result<(), Option<gst::ErrorMessage>> {
fn flush_current_buffer(&self) -> Result<(), Option<gst::ErrorMessage>> {
let upload_part_req: UploadPart = self.create_upload_part_request()?;
let mut state = self.state.lock().unwrap();
@ -210,7 +207,7 @@ impl S3Sink {
OnError::Abort => {
gst::log!(
CAT,
obj: element,
imp: self,
"Aborting multipart upload request with id: {}",
state.upload_id
);
@ -218,13 +215,13 @@ impl S3Sink {
Ok(()) => {
gst::log!(
CAT,
obj: element,
imp: self,
"Aborting multipart upload request succeeded."
);
}
Err(err) => gst::error!(
CAT,
obj: element,
imp: self,
"Aborting multipart upload failed: {}",
err.to_string()
),
@ -233,7 +230,7 @@ impl S3Sink {
OnError::Complete => {
gst::log!(
CAT,
obj: element,
imp: self,
"Completing multipart upload request with id: {}",
state.upload_id
);
@ -241,13 +238,13 @@ impl S3Sink {
Ok(()) => {
gst::log!(
CAT,
obj: element,
imp: self,
"Complete multipart upload request succeeded."
);
}
Err(err) => gst::error!(
CAT,
obj: element,
imp: self,
"Completing multipart upload failed: {}",
err.to_string()
),
@ -269,7 +266,7 @@ impl S3Sink {
.build();
state.completed_parts.push(completed_part);
gst::info!(CAT, obj: element, "Uploaded part {}", part_number);
gst::info!(CAT, imp: self, "Uploaded part {}", part_number);
Ok(())
}
@ -344,7 +341,7 @@ impl S3Sink {
let bucket = Some(url.bucket.clone());
let key = Some(url.object.clone());
let content_type = settings.content_type.clone();
let metadata = settings.to_metadata(&self.instance());
let metadata = settings.to_metadata(self);
client
.create_multipart_upload()
@ -429,8 +426,8 @@ impl S3Sink {
})
}
fn finalize_upload(&self, element: &super::S3Sink) -> Result<(), gst::ErrorMessage> {
if self.flush_current_buffer(element).is_err() {
fn finalize_upload(&self) -> Result<(), gst::ErrorMessage> {
if self.flush_current_buffer().is_err() {
return Err(gst::error_msg!(
gst::ResourceError::Settings,
["Failed to flush internal buffer."]
@ -561,11 +558,7 @@ impl S3Sink {
Ok(())
}
fn update_buffer(
&self,
src: &[u8],
element: &super::S3Sink,
) -> Result<(), Option<gst::ErrorMessage>> {
fn update_buffer(&self, src: &[u8]) -> Result<(), Option<gst::ErrorMessage>> {
let mut state = self.state.lock().unwrap();
let started_state = match *state {
State::Started(ref mut started_state) => started_state,
@ -585,11 +578,11 @@ impl S3Sink {
drop(state);
if do_flush {
self.flush_current_buffer(element)?;
self.flush_current_buffer()?;
}
if to_copy < src.len() {
self.update_buffer(tail, element)?;
self.update_buffer(tail)?;
}
Ok(())
@ -608,11 +601,7 @@ impl S3Sink {
};
}
fn set_uri(
self: &S3Sink,
object: &super::S3Sink,
url_str: Option<&str>,
) -> Result<(), glib::Error> {
fn set_uri(self: &S3Sink, url_str: Option<&str>) -> Result<(), glib::Error> {
let state = self.state.lock().unwrap();
if let State::Started { .. } = *state {
@ -629,7 +618,7 @@ impl S3Sink {
return Ok(());
}
gst::debug!(CAT, obj: object, "Setting uri to {:?}", url_str);
gst::debug!(CAT, imp: self, "Setting uri to {:?}", url_str);
let url_str = url_str.unwrap();
match parse_s3_url(url_str) {
@ -764,18 +753,12 @@ impl ObjectImpl for S3Sink {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
gst::debug!(
CAT,
obj: obj,
imp: self,
"Setting property '{}' to '{:?}'",
pspec.name(),
value
@ -787,7 +770,7 @@ impl ObjectImpl for S3Sink {
.get::<Option<String>>()
.expect("type checked upstream");
if settings.key.is_some() {
let _ = self.set_uri(obj, Some(&settings.to_uri()));
let _ = self.set_uri(Some(&settings.to_uri()));
}
}
"key" => {
@ -795,21 +778,21 @@ impl ObjectImpl for S3Sink {
.get::<Option<String>>()
.expect("type checked upstream");
if settings.bucket.is_some() {
let _ = self.set_uri(obj, Some(&settings.to_uri()));
let _ = self.set_uri(Some(&settings.to_uri()));
}
}
"region" => {
let region = value.get::<String>().expect("type checked upstream");
settings.region = Region::new(region);
if settings.key.is_some() && settings.bucket.is_some() {
let _ = self.set_uri(obj, Some(&settings.to_uri()));
let _ = self.set_uri(Some(&settings.to_uri()));
}
}
"part-size" => {
settings.buffer_size = value.get::<u64>().expect("type checked upstream");
}
"uri" => {
let _ = self.set_uri(obj, value.get().expect("type checked upstream"));
let _ = self.set_uri(value.get().expect("type checked upstream"));
}
"access-key" => {
settings.access_key = value.get().expect("type checked upstream");
@ -864,14 +847,14 @@ impl ObjectImpl for S3Sink {
.get::<Option<String>>()
.expect("type checked upstream");
if settings.key.is_some() && settings.bucket.is_some() {
let _ = self.set_uri(obj, Some(&settings.to_uri()));
let _ = self.set_uri(Some(&settings.to_uri()));
}
}
_ => unimplemented!(),
}
}
fn property(&self, _: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
@ -954,77 +937,68 @@ impl URIHandlerImpl for S3Sink {
&["s3"]
}
fn uri(&self, _: &Self::Type) -> Option<String> {
fn uri(&self) -> Option<String> {
self.url.lock().unwrap().as_ref().map(|s| s.to_string())
}
fn set_uri(&self, element: &Self::Type, uri: &str) -> Result<(), glib::Error> {
self.set_uri(element, Some(uri))
fn set_uri(&self, uri: &str) -> Result<(), glib::Error> {
self.set_uri(Some(uri))
}
}
impl BaseSinkImpl for S3Sink {
fn start(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
self.start()
}
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
let mut state = self.state.lock().unwrap();
*state = State::Stopped;
gst::info!(CAT, obj: element, "Stopped");
gst::info!(CAT, imp: self, "Stopped");
Ok(())
}
fn render(
&self,
element: &Self::Type,
buffer: &gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
fn render(&self, buffer: &gst::Buffer) -> Result<gst::FlowSuccess, gst::FlowError> {
if let State::Stopped = *self.state.lock().unwrap() {
gst::element_error!(element, gst::CoreError::Failed, ["Not started yet"]);
gst::element_imp_error!(self, gst::CoreError::Failed, ["Not started yet"]);
return Err(gst::FlowError::Error);
}
gst::trace!(CAT, obj: element, "Rendering {:?}", buffer);
gst::trace!(CAT, imp: self, "Rendering {:?}", buffer);
let map = buffer.map_readable().map_err(|_| {
gst::element_error!(element, gst::CoreError::Failed, ["Failed to map buffer"]);
gst::element_imp_error!(self, gst::CoreError::Failed, ["Failed to map buffer"]);
gst::FlowError::Error
})?;
match self.update_buffer(&map, element) {
match self.update_buffer(&map) {
Ok(_) => Ok(gst::FlowSuccess::Ok),
Err(err) => match err {
Some(error_message) => {
gst::error!(
CAT,
obj: element,
"Multipart upload failed: {}",
error_message
);
element.post_error_message(error_message);
gst::error!(CAT, imp: self, "Multipart upload failed: {}", error_message);
self.post_error_message(error_message);
Err(gst::FlowError::Error)
}
_ => {
gst::info!(CAT, obj: element, "Upload interrupted. Flushing...");
gst::info!(CAT, imp: self, "Upload interrupted. Flushing...");
Err(gst::FlowError::Flushing)
}
},
}
}
fn unlock(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn unlock(&self) -> Result<(), gst::ErrorMessage> {
self.cancel();
Ok(())
}
fn event(&self, element: &Self::Type, event: gst::Event) -> bool {
fn event(&self, event: gst::Event) -> bool {
if let gst::EventView::Eos(_) = event.view() {
if let Err(error_message) = self.finalize_upload(element) {
if let Err(error_message) = self.finalize_upload() {
gst::error!(
CAT,
obj: element,
imp: self,
"Failed to finalize the upload: {}",
error_message
);
@ -1032,6 +1006,6 @@ impl BaseSinkImpl for S3Sink {
}
}
BaseSinkImplExt::parent_event(self, element, event)
BaseSinkImplExt::parent_event(self, event)
}
}

View file

@ -157,7 +157,7 @@ impl S3Src {
Ok(Client::from_conf(config))
}
fn set_uri(self: &S3Src, _: &super::S3Src, url_str: Option<&str>) -> Result<(), glib::Error> {
fn set_uri(self: &S3Src, url_str: Option<&str>) -> Result<(), glib::Error> {
let state = self.state.lock().unwrap();
if let StreamingState::Started { .. } = *state {
@ -187,12 +187,7 @@ impl S3Src {
}
}
fn head(
self: &S3Src,
src: &super::S3Src,
client: &Client,
url: &GstS3Url,
) -> Result<u64, gst::ErrorMessage> {
fn head(self: &S3Src, client: &Client, url: &GstS3Url) -> Result<u64, gst::ErrorMessage> {
let head_object = client
.head_object()
.set_bucket(Some(url.bucket.clone()))
@ -216,7 +211,7 @@ impl S3Src {
gst::info!(
CAT,
obj: src,
imp: self,
"HEAD success, content length = {}",
output.content_length
);
@ -225,12 +220,7 @@ impl S3Src {
}
/* Returns the bytes, Some(error) if one occured, or a None error if interrupted */
fn get(
self: &S3Src,
src: &super::S3Src,
offset: u64,
length: u64,
) -> Result<Bytes, Option<gst::ErrorMessage>> {
fn get(self: &S3Src, offset: u64, length: u64) -> Result<Bytes, Option<gst::ErrorMessage>> {
let state = self.state.lock().unwrap();
let (url, client) = match *state {
@ -256,7 +246,7 @@ impl S3Src {
gst::debug!(
CAT,
obj: src,
imp: self,
"Requesting range: {}-{}",
offset,
offset + length - 1
@ -273,7 +263,7 @@ impl S3Src {
WaitError::Cancelled => None,
})?;
gst::debug!(CAT, obj: src, "Read {} bytes", output.content_length);
gst::debug!(CAT, imp: self, "Read {} bytes", output.content_length);
s3utils::wait_stream(&self.canceller, &mut output.body).map_err(|err| match err {
WaitError::FutureError(err) => Some(gst::error_msg!(
@ -346,19 +336,13 @@ impl ObjectImpl for S3Src {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"uri" => {
drop(settings);
let _ = self.set_uri(obj, value.get().expect("type checked upstream"));
let _ = self.set_uri(value.get().expect("type checked upstream"));
}
"access-key" => {
settings.access_key = value.get().expect("type checked upstream");
@ -399,7 +383,7 @@ impl ObjectImpl for S3Src {
}
}
fn property(&self, _: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
@ -425,9 +409,10 @@ impl ObjectImpl for S3Src {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.set_format(gst::Format::Bytes);
/* Set a larger default blocksize to make read more efficient */
obj.set_blocksize(256 * 1024);
@ -475,23 +460,23 @@ impl URIHandlerImpl for S3Src {
&["s3"]
}
fn uri(&self, _: &Self::Type) -> Option<String> {
fn uri(&self) -> Option<String> {
let settings = self.settings.lock().unwrap();
settings.url.as_ref().map(|s| s.to_string())
}
fn set_uri(&self, element: &Self::Type, uri: &str) -> Result<(), glib::Error> {
self.set_uri(element, Some(uri))
fn set_uri(&self, uri: &str) -> Result<(), glib::Error> {
self.set_uri(Some(uri))
}
}
impl BaseSrcImpl for S3Src {
fn is_seekable(&self, _: &Self::Type) -> bool {
fn is_seekable(&self) -> bool {
true
}
fn size(&self, _: &Self::Type) -> Option<u64> {
fn size(&self) -> Option<u64> {
let state = self.state.lock().unwrap();
match *state {
StreamingState::Stopped => None,
@ -499,7 +484,7 @@ impl BaseSrcImpl for S3Src {
}
}
fn start(&self, src: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
let mut state = self.state.lock().unwrap();
if let StreamingState::Started { .. } = *state {
@ -519,7 +504,7 @@ impl BaseSrcImpl for S3Src {
drop(settings);
if let Ok(s3client) = self.connect(&s3url) {
let size = self.head(src, &s3client, &s3url)?;
let size = self.head(&s3client, &s3url)?;
*state = StreamingState::Started {
url: s3url,
@ -536,7 +521,7 @@ impl BaseSrcImpl for S3Src {
}
}
fn stop(&self, _: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
// First, stop any asynchronous tasks if we're running, as they will have the state lock
self.cancel();
@ -551,7 +536,7 @@ impl BaseSrcImpl for S3Src {
Ok(())
}
fn query(&self, src: &Self::Type, query: &mut gst::QueryRef) -> bool {
fn query(&self, query: &mut gst::QueryRef) -> bool {
if let gst::QueryViewMut::Scheduling(q) = query.view_mut() {
q.set(
gst::SchedulingFlags::SEQUENTIAL | gst::SchedulingFlags::BANDWIDTH_LIMITED,
@ -563,18 +548,17 @@ impl BaseSrcImpl for S3Src {
return true;
}
BaseSrcImplExt::parent_query(self, src, query)
BaseSrcImplExt::parent_query(self, query)
}
fn create(
&self,
src: &Self::Type,
offset: u64,
buffer: Option<&mut gst::BufferRef>,
length: u32,
) -> Result<CreateSuccess, gst::FlowError> {
// FIXME: sanity check on offset and length
let data = self.get(src, offset, u64::from(length));
let data = self.get(offset, u64::from(length));
match data {
/* Got data */
@ -592,18 +576,18 @@ impl BaseSrcImpl for S3Src {
Err(None) => Err(gst::FlowError::Flushing),
/* Actual Error */
Err(Some(err)) => {
gst::error!(CAT, obj: src, "Could not GET: {}", err);
gst::error!(CAT, imp: self, "Could not GET: {}", err);
Err(gst::FlowError::Error)
}
}
}
/* FIXME: implement */
fn do_seek(&self, _: &Self::Type, _: &mut gst::Segment) -> bool {
fn do_seek(&self, _: &mut gst::Segment) -> bool {
true
}
fn unlock(&self, _: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn unlock(&self) -> Result<(), gst::ErrorMessage> {
self.cancel();
Ok(())
}

View file

@ -134,15 +134,15 @@ impl Default for State {
}
}
#[derive(Default, Clone)]
#[derive(Default)]
pub struct HlsSink3 {
settings: Arc<Mutex<Settings>>,
state: Arc<Mutex<State>>,
}
impl HlsSink3 {
fn start(&self, element: &super::HlsSink3) {
gst::info!(CAT, obj: element, "Starting");
fn start(&self) {
gst::info!(CAT, imp: self, "Starting");
let (target_duration, playlist_type) = {
let settings = self.settings.lock().unwrap();
@ -158,14 +158,10 @@ impl HlsSink3 {
}
}
fn on_format_location(
&self,
element: &super::HlsSink3,
fragment_id: u32,
) -> Result<String, String> {
fn on_format_location(&self, fragment_id: u32) -> Result<String, String> {
gst::info!(
CAT,
obj: element,
imp: self,
"Starting the formatting of the fragment-id: {}",
fragment_id
);
@ -181,14 +177,15 @@ impl HlsSink3 {
let segment_file_location = settings.segment_formatter.segment(fragment_id);
gst::trace!(
CAT,
obj: element,
imp: self,
"Segment location formatted: {}",
segment_file_location
);
state.current_segment_location = Some(segment_file_location.clone());
let fragment_stream = element
let fragment_stream = self
.instance()
.emit_by_name::<Option<gio::OutputStream>>(
SIGNAL_GET_FRAGMENT_STREAM,
&[&segment_file_location],
@ -201,18 +198,14 @@ impl HlsSink3 {
gst::info!(
CAT,
obj: element,
imp: self,
"New segment location: {:?}",
state.current_segment_location.as_ref()
);
Ok(segment_file_location)
}
fn new_file_stream<P>(
&self,
element: &super::HlsSink3,
location: &P,
) -> Result<gio::OutputStream, String>
fn new_file_stream<P>(&self, location: &P) -> Result<gio::OutputStream, String>
where
P: AsRef<path::Path>,
{
@ -225,20 +218,20 @@ impl HlsSink3 {
err.to_string(),
]
);
element.post_error_message(error_msg);
self.post_error_message(error_msg);
err.to_string()
})?;
Ok(gio::WriteOutputStream::new(file).upcast())
}
fn delete_fragment<P>(&self, element: &super::HlsSink3, location: &P)
fn delete_fragment<P>(&self, location: &P)
where
P: AsRef<path::Path>,
{
let _ = fs::remove_file(location).map_err(|err| {
gst::warning!(
CAT,
obj: element,
imp: self,
"Could not delete segment file: {}",
err.to_string()
);
@ -247,10 +240,9 @@ impl HlsSink3 {
fn write_playlist(
&self,
element: &super::HlsSink3,
fragment_closed_at: Option<gst::ClockTime>,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::info!(CAT, obj: element, "Preparing to write new playlist");
gst::info!(CAT, imp: self, "Preparing to write new playlist");
let mut state_guard = self.state.lock().unwrap();
let state = match &mut *state_guard {
@ -258,7 +250,7 @@ impl HlsSink3 {
State::Started(s) => s,
};
gst::info!(CAT, obj: element, "COUNT {}", state.playlist.len());
gst::info!(CAT, imp: self, "COUNT {}", state.playlist.len());
// Only add fragment if it's complete.
if let Some(fragment_closed) = fragment_closed_at {
@ -283,7 +275,8 @@ impl HlsSink3 {
// Acquires the playlist file handle so we can update it with new content. By default, this
// is expected to be the same file every time.
let mut playlist_stream = element
let mut playlist_stream = self
.instance()
.emit_by_name::<Option<gio::OutputStream>>(
SIGNAL_GET_PLAYLIST_STREAM,
&[&playlist_location],
@ -291,7 +284,7 @@ impl HlsSink3 {
.ok_or_else(|| {
gst::error!(
CAT,
obj: element,
imp: self,
"Could not get stream to write playlist content",
);
gst::StateChangeError
@ -304,7 +297,7 @@ impl HlsSink3 {
.map_err(|err| {
gst::error!(
CAT,
obj: element,
imp: self,
"Could not write new playlist: {}",
err.to_string()
);
@ -313,7 +306,7 @@ impl HlsSink3 {
playlist_stream.flush().map_err(|err| {
gst::error!(
CAT,
obj: element,
imp: self,
"Could not flush playlist: {}",
err.to_string()
);
@ -325,16 +318,17 @@ impl HlsSink3 {
if state.old_segment_locations.len() > max_num_segments {
for _ in 0..state.old_segment_locations.len() - max_num_segments {
let old_segment_location = state.old_segment_locations.remove(0);
if !element
if !self
.instance()
.emit_by_name::<bool>(SIGNAL_DELETE_FRAGMENT, &[&old_segment_location])
{
gst::error!(CAT, obj: element, "Could not delete fragment");
gst::error!(CAT, imp: self, "Could not delete fragment");
}
}
}
}
gst::debug!(CAT, obj: element, "Wrote new playlist file!");
gst::debug!(CAT, imp: self, "Wrote new playlist file!");
Ok(gst::StateChangeSuccess::Success)
}
@ -350,23 +344,20 @@ impl HlsSink3 {
}
}
fn write_final_playlist(
&self,
element: &super::HlsSink3,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::debug!(CAT, obj: element, "Preparing to write final playlist");
self.write_playlist(element, None)
fn write_final_playlist(&self) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::debug!(CAT, imp: self, "Preparing to write final playlist");
self.write_playlist(None)
}
fn stop(&self, element: &super::HlsSink3) {
gst::debug!(CAT, obj: element, "Stopping");
fn stop(&self) {
gst::debug!(CAT, imp: self, "Stopping");
let mut state = self.state.lock().unwrap();
if let State::Started(_) = *state {
*state = State::Stopped;
}
gst::debug!(CAT, obj: element, "Stopped");
gst::debug!(CAT, imp: self, "Stopped");
}
}
@ -379,7 +370,7 @@ impl ObjectSubclass for HlsSink3 {
impl BinImpl for HlsSink3 {
#[allow(clippy::single_match)]
fn handle_message(&self, element: &Self::Type, msg: gst::Message) {
fn handle_message(&self, msg: gst::Message) {
use gst::MessageView;
match msg.view() {
@ -410,14 +401,13 @@ impl BinImpl for HlsSink3 {
"splitmuxsink-fragment-closed" => {
let s = msg.structure().unwrap();
if let Ok(fragment_closed_at) = s.get::<gst::ClockTime>("running-time") {
self.write_playlist(element, Some(fragment_closed_at))
.unwrap();
self.write_playlist(Some(fragment_closed_at)).unwrap();
}
}
_ => {}
}
}
_ => self.parent_handle_message(element, msg),
_ => self.parent_handle_message(msg),
}
}
}
@ -469,13 +459,7 @@ impl ObjectImpl for HlsSink3 {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
"location" => {
@ -531,7 +515,7 @@ impl ObjectImpl for HlsSink3 {
};
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
"location" => settings.location.to_value(),
@ -568,7 +552,7 @@ impl ObjectImpl for HlsSink3 {
Some(
hlssink3
.new_file_stream(&element, &playlist_location)
.new_file_stream(&playlist_location)
.ok()?
.to_value(),
)
@ -592,7 +576,7 @@ impl ObjectImpl for HlsSink3 {
Some(
hlssink3
.new_file_stream(&element, &fragment_location)
.new_file_stream(&fragment_location)
.ok()?
.to_value(),
)
@ -611,7 +595,7 @@ impl ObjectImpl for HlsSink3 {
let fragment_location = args[1].get::<String>().expect("signal arg");
let hlssink3 = element.imp();
hlssink3.delete_fragment(&element, &fragment_location);
hlssink3.delete_fragment(&fragment_location);
Some(true.to_value())
})
.accumulator(|_hint, ret, value| {
@ -626,9 +610,10 @@ impl ObjectImpl for HlsSink3 {
SIGNALS.as_ref()
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.set_element_flags(gst::ElementFlags::SINK);
obj.set_suppressed_flags(gst::ElementFlags::SINK | gst::ElementFlags::SOURCE);
@ -653,22 +638,20 @@ impl ObjectImpl for HlsSink3 {
obj.add(&settings.splitmuxsink).unwrap();
settings.splitmuxsink.connect("format-location", false, {
let element_weak = obj.downgrade();
let self_weak = self.downgrade();
move |args| {
let element = match element_weak.upgrade() {
Some(element) => element,
let self_ = match self_weak.upgrade() {
Some(self_) => self_,
None => return Some(None::<String>.to_value()),
};
let hlssink3 = element.imp();
let fragment_id = args[1].get::<u32>().unwrap();
gst::info!(CAT, obj: &element, "Got fragment-id: {}", fragment_id);
gst::info!(CAT, imp: self_, "Got fragment-id: {}", fragment_id);
match hlssink3.on_format_location(&element, fragment_id) {
match self_.on_format_location(fragment_id) {
Ok(segment_location) => Some(segment_location.to_value()),
Err(err) => {
gst::error!(CAT, obj: &element, "on format-location handler: {}", err);
gst::error!(CAT, imp: self_, "on format-location handler: {}", err);
Some("unknown_segment".to_value())
}
}
@ -723,14 +706,13 @@ impl ElementImpl for HlsSink3 {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
if let gst::StateChange::NullToReady = transition {
self.start(element);
self.start();
}
let ret = self.parent_change_state(element, transition)?;
let ret = self.parent_change_state(transition)?;
match transition {
gst::StateChange::PausedToReady => {
@ -750,11 +732,11 @@ impl ElementImpl for HlsSink3 {
};
if write_final {
self.write_final_playlist(element)?;
self.write_final_playlist()?;
}
}
gst::StateChange::ReadyToNull => {
self.stop(element);
self.stop();
}
_ => (),
}
@ -764,7 +746,6 @@ impl ElementImpl for HlsSink3 {
fn request_new_pad(
&self,
element: &Self::Type,
templ: &gst::PadTemplate,
_name: Option<String>,
_caps: Option<&gst::Caps>,
@ -775,7 +756,7 @@ impl ElementImpl for HlsSink3 {
if settings.audio_sink {
gst::debug!(
CAT,
obj: element,
imp: self,
"requested_new_pad: audio pad is already set"
);
return None;
@ -785,7 +766,7 @@ impl ElementImpl for HlsSink3 {
let sink_pad =
gst::GhostPad::from_template_with_target(templ, Some("audio"), &peer_pad)
.unwrap();
element.add_pad(&sink_pad).unwrap();
self.instance().add_pad(&sink_pad).unwrap();
sink_pad.set_active(true).unwrap();
settings.audio_sink = true;
@ -795,7 +776,7 @@ impl ElementImpl for HlsSink3 {
if settings.video_sink {
gst::debug!(
CAT,
obj: element,
imp: self,
"requested_new_pad: video pad is already set"
);
return None;
@ -805,7 +786,7 @@ impl ElementImpl for HlsSink3 {
let sink_pad =
gst::GhostPad::from_template_with_target(templ, Some("video"), &peer_pad)
.unwrap();
element.add_pad(&sink_pad).unwrap();
self.instance().add_pad(&sink_pad).unwrap();
sink_pad.set_active(true).unwrap();
settings.video_sink = true;
@ -814,7 +795,7 @@ impl ElementImpl for HlsSink3 {
other_name => {
gst::debug!(
CAT,
obj: element,
imp: self,
"requested_new_pad: name \"{}\" is not audio or video",
other_name
);
@ -823,7 +804,7 @@ impl ElementImpl for HlsSink3 {
}
}
fn release_pad(&self, element: &Self::Type, pad: &gst::Pad) {
fn release_pad(&self, pad: &gst::Pad) {
let mut settings = self.settings.lock().unwrap();
if !settings.audio_sink && !settings.video_sink {
@ -836,7 +817,7 @@ impl ElementImpl for HlsSink3 {
}
pad.set_active(false).unwrap();
element.remove_pad(pad).unwrap();
self.instance().remove_pad(pad).unwrap();
if "audio" == ghost_pad.name() {
settings.audio_sink = false;

View file

@ -58,9 +58,10 @@ impl ObjectSubclass for OnvifMetadataCombiner {
}
impl ObjectImpl for OnvifMetadataCombiner {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.media_sink_pad).unwrap();
obj.add_pad(&self.meta_sink_pad).unwrap();
}
@ -127,36 +128,30 @@ impl ElementImpl for OnvifMetadataCombiner {
fn request_new_pad(
&self,
element: &Self::Type,
_templ: &gst::PadTemplate,
_name: Option<String>,
_caps: Option<&gst::Caps>,
) -> Option<gst::Pad> {
gst::error!(
CAT,
obj: element,
imp: self,
"onvifmetadatacombiner doesn't expose request pads"
);
None
}
fn release_pad(&self, element: &Self::Type, _pad: &gst::Pad) {
fn release_pad(&self, _pad: &gst::Pad) {
gst::error!(
CAT,
obj: element,
imp: self,
"onvifmetadatacombiner doesn't expose request pads"
);
}
}
impl OnvifMetadataCombiner {
fn consume_meta(
&self,
state: &mut State,
element: &super::OnvifMetadataCombiner,
end: gst::ClockTime,
) -> Result<bool, gst::FlowError> {
fn consume_meta(&self, state: &mut State, end: gst::ClockTime) -> Result<bool, gst::FlowError> {
while let Some(buffer) = self.meta_sink_pad.peek_buffer() {
// Skip over gap buffers
if buffer.flags().contains(gst::BufferFlags::GAP)
@ -168,8 +163,8 @@ impl OnvifMetadataCombiner {
}
let meta_ts = crate::lookup_reference_timestamp(&buffer).ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Parsed metadata buffer should hold reference timestamp"]
);
@ -188,7 +183,6 @@ impl OnvifMetadataCombiner {
fn media_buffer_duration(
&self,
element: &super::OnvifMetadataCombiner,
current_media_buffer: &gst::Buffer,
timeout: bool,
) -> Option<gst::ClockTime> {
@ -196,7 +190,7 @@ impl OnvifMetadataCombiner {
Some(duration) => {
gst::log!(
CAT,
obj: element,
imp: self,
"Current media buffer has a duration, using it: {}",
duration
);
@ -210,7 +204,7 @@ impl OnvifMetadataCombiner {
gst::log!(
CAT,
obj: element,
imp: self,
"calculated duration for current media buffer from next buffer: {}",
duration
);
@ -220,7 +214,7 @@ impl OnvifMetadataCombiner {
None => {
gst::log!(
CAT,
obj: element,
imp: self,
"could not calculate duration for current media buffer"
);
Some(gst::ClockTime::from_nseconds(0))
@ -229,14 +223,14 @@ impl OnvifMetadataCombiner {
} else if timeout {
gst::log!(
CAT,
obj: element,
imp: self,
"could not calculate duration for current media buffer"
);
Some(gst::ClockTime::from_nseconds(0))
} else {
gst::trace!(
CAT,
obj: element,
imp: self,
"No next buffer to peek at yet to calculate duration"
);
None
@ -248,7 +242,6 @@ impl OnvifMetadataCombiner {
fn consume_media(
&self,
state: &mut State,
element: &super::OnvifMetadataCombiner,
timeout: bool,
) -> Result<Option<gst::Buffer>, gst::FlowError> {
if let Some(current_media_buffer) = state
@ -259,11 +252,11 @@ impl OnvifMetadataCombiner {
if let Some(current_media_start) =
crate::lookup_reference_timestamp(&current_media_buffer)
{
match self.media_buffer_duration(element, &current_media_buffer, timeout) {
match self.media_buffer_duration(&current_media_buffer, timeout) {
Some(duration) => {
let end = current_media_start + duration;
if self.consume_meta(state, element, end)? {
if self.consume_meta(state, end)? {
Ok(Some(current_media_buffer))
} else {
state.current_media_buffer = Some(current_media_buffer);
@ -285,16 +278,12 @@ impl OnvifMetadataCombiner {
}
impl AggregatorImpl for OnvifMetadataCombiner {
fn aggregate(
&self,
element: &Self::Type,
timeout: bool,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::trace!(CAT, obj: element, "aggregate, timeout: {}", timeout);
fn aggregate(&self, timeout: bool) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::trace!(CAT, imp: self, "aggregate, timeout: {}", timeout);
let mut state = self.state.lock().unwrap();
if let Some(mut buffer) = self.consume_media(&mut state, element, timeout)? {
if let Some(mut buffer) = self.consume_media(&mut state, timeout)? {
let mut buflist = gst::BufferList::new();
{
@ -321,11 +310,11 @@ impl AggregatorImpl for OnvifMetadataCombiner {
.unwrap_or_else(|| gst::ClockTime::from_nseconds(0)),
);
gst::log!(CAT, obj: element, "Updating position: {:?}", position);
gst::log!(CAT, imp: self, "Updating position: {:?}", position);
element.set_position(position);
self.instance().set_position(position);
self.finish_buffer(element, buffer)
self.finish_buffer(buffer)
} else if self.media_sink_pad.is_eos() {
Err(gst::FlowError::Eos)
} else {
@ -333,7 +322,7 @@ impl AggregatorImpl for OnvifMetadataCombiner {
}
}
fn src_query(&self, aggregator: &Self::Type, query: &mut gst::QueryRef) -> bool {
fn src_query(&self, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
match query.view_mut() {
@ -344,6 +333,7 @@ impl AggregatorImpl for OnvifMetadataCombiner {
| QueryViewMut::Allocation(..) => self.media_sink_pad.peer_query(query),
QueryViewMut::AcceptCaps(q) => {
let caps = q.caps_owned();
let aggregator = self.instance();
let class = aggregator.class();
let templ = class.pad_template("media").unwrap();
let templ_caps = templ.caps();
@ -352,40 +342,34 @@ impl AggregatorImpl for OnvifMetadataCombiner {
true
}
_ => self.parent_src_query(aggregator, query),
_ => self.parent_src_query(query),
}
}
fn sink_event(
&self,
aggregator: &Self::Type,
aggregator_pad: &gst_base::AggregatorPad,
event: gst::Event,
) -> bool {
fn sink_event(&self, aggregator_pad: &gst_base::AggregatorPad, event: gst::Event) -> bool {
use gst::EventView;
match event.view() {
EventView::Caps(e) => {
if aggregator_pad.upcast_ref::<gst::Pad>() == &self.media_sink_pad {
gst::info!(CAT, obj: aggregator, "Pushing caps {}", e.caps());
aggregator.set_src_caps(&e.caps_owned());
gst::info!(CAT, imp: self, "Pushing caps {}", e.caps());
self.instance().set_src_caps(&e.caps_owned());
}
true
}
EventView::Segment(e) => {
if aggregator_pad.upcast_ref::<gst::Pad>() == &self.media_sink_pad {
aggregator.update_segment(e.segment());
self.instance().update_segment(e.segment());
}
self.parent_sink_event(aggregator, aggregator_pad, event)
self.parent_sink_event(aggregator_pad, event)
}
_ => self.parent_sink_event(aggregator, aggregator_pad, event),
_ => self.parent_sink_event(aggregator_pad, event),
}
}
fn sink_query(
&self,
aggregator: &Self::Type,
aggregator_pad: &gst_base::AggregatorPad,
query: &mut gst::QueryRef,
) -> bool {
@ -397,18 +381,17 @@ impl AggregatorImpl for OnvifMetadataCombiner {
| QueryViewMut::Uri(..)
| QueryViewMut::Allocation(..) => {
if aggregator_pad == &self.media_sink_pad {
let srcpad = aggregator.src_pad();
srcpad.peer_query(query)
self.instance().src_pad().peer_query(query)
} else {
self.parent_sink_query(aggregator, aggregator_pad, query)
self.parent_sink_query(aggregator_pad, query)
}
}
QueryViewMut::Caps(q) => {
if aggregator_pad == &self.media_sink_pad {
let srcpad = aggregator.src_pad();
srcpad.peer_query(query)
self.instance().src_pad().peer_query(query)
} else {
let filter = q.filter_owned();
let aggregator = self.instance();
let class = aggregator.class();
let templ = class.pad_template("meta").unwrap();
let templ_caps = templ.caps();
@ -426,10 +409,10 @@ impl AggregatorImpl for OnvifMetadataCombiner {
}
QueryViewMut::AcceptCaps(q) => {
if aggregator_pad.upcast_ref::<gst::Pad>() == &self.media_sink_pad {
let srcpad = aggregator.src_pad();
srcpad.peer_query(query);
self.instance().src_pad().peer_query(query);
} else {
let caps = q.caps_owned();
let aggregator = self.instance();
let class = aggregator.class();
let templ = class.pad_template("meta").unwrap();
let templ_caps = templ.caps();
@ -439,15 +422,15 @@ impl AggregatorImpl for OnvifMetadataCombiner {
true
}
_ => self.parent_src_query(aggregator, query),
_ => self.parent_src_query(query),
}
}
fn next_time(&self, aggregator: &Self::Type) -> Option<gst::ClockTime> {
aggregator.simple_get_next_time()
fn next_time(&self) -> Option<gst::ClockTime> {
self.instance().simple_get_next_time()
}
fn negotiate(&self, _aggregator: &Self::Type) -> bool {
fn negotiate(&self) -> bool {
true
}
}

View file

@ -82,7 +82,8 @@ impl ElementImpl for OnvifMetadataDepay {
}
impl RTPBaseDepayloadImpl for OnvifMetadataDepay {
fn set_caps(&self, element: &Self::Type, _caps: &gst::Caps) -> Result<(), gst::LoggableError> {
fn set_caps(&self, _caps: &gst::Caps) -> Result<(), gst::LoggableError> {
let element = self.instance();
let src_pad = element.src_pad();
let src_caps = src_pad.pad_template_caps();
src_pad.push_event(gst::event::Caps::builder(&src_caps).build());
@ -92,15 +93,14 @@ impl RTPBaseDepayloadImpl for OnvifMetadataDepay {
fn process_rtp_packet(
&self,
element: &Self::Type,
rtp_buffer: &gst_rtp::RTPBuffer<gst_rtp::rtp_buffer::Readable>,
) -> Option<gst::Buffer> {
// Retrieve the payload subbuffer
let payload_buffer = match rtp_buffer.payload_buffer() {
Ok(buffer) => buffer,
Err(..) => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to retrieve RTP buffer payload"]
);
@ -116,7 +116,7 @@ impl RTPBaseDepayloadImpl for OnvifMetadataDepay {
.flags()
.contains(gst::BufferFlags::DISCONT)
{
gst::debug!(CAT, obj: element, "processing discont RTP buffer");
gst::debug!(CAT, imp: self, "processing discont RTP buffer");
state.adapter.clear();
}
@ -132,8 +132,8 @@ impl RTPBaseDepayloadImpl for OnvifMetadataDepay {
let buffer = match state.adapter.take_buffer(available) {
Ok(buffer) => buffer,
Err(err) => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to empty adapter: {}", err]
);
@ -148,12 +148,7 @@ impl RTPBaseDepayloadImpl for OnvifMetadataDepay {
let utf8 = match std::str::from_utf8(map.as_ref()) {
Ok(s) => s,
Err(err) => {
gst::warning!(
CAT,
obj: element,
"Failed to decode payload as UTF-8: {}",
err
);
gst::warning!(CAT, imp: self, "Failed to decode payload as UTF-8: {}", err);
return None;
}
@ -183,7 +178,7 @@ impl RTPBaseDepayloadImpl for OnvifMetadataDepay {
}
},
Err(err) => {
gst::warning!(CAT, obj: element, "Invalid XML in payload: {}", err);
gst::warning!(CAT, imp: self, "Invalid XML in payload: {}", err);
return None;
}
@ -197,7 +192,7 @@ impl RTPBaseDepayloadImpl for OnvifMetadataDepay {
if !forward {
gst::warning!(
CAT,
obj: element,
imp: self,
"document must start with tt:MetadataStream element",
);

View file

@ -72,17 +72,14 @@ pub struct OnvifMetadataOverlay {
}
impl OnvifMetadataOverlay {
fn negotiate(
&self,
element: &super::OnvifMetadataOverlay,
) -> Result<gst::FlowSuccess, gst::FlowError> {
fn negotiate(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
let video_info = {
let state = self.state.lock().unwrap();
match state.video_info.as_ref() {
Some(video_info) => Ok(video_info.clone()),
None => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Negotiation,
["Element hasn't received valid video caps at negotiation time"]
);
@ -115,7 +112,7 @@ impl OnvifMetadataOverlay {
gst::debug!(
CAT,
obj: element,
imp: self,
"upstream has meta: {}, downstream accepts meta: {}",
upstream_has_meta,
downstream_accepts_meta
@ -138,7 +135,7 @@ impl OnvifMetadataOverlay {
.find_allocation_meta::<gst_video::VideoOverlayCompositionMeta>()
.is_some();
gst::debug!(CAT, obj: element, "attach meta: {}", attach);
gst::debug!(CAT, imp: self, "attach meta: {}", attach);
self.state.lock().unwrap().attach = attach;
@ -291,12 +288,7 @@ impl OnvifMetadataOverlay {
}
// Update our overlay composition with a set of rectangles
fn overlay_shapes(
&self,
state: &mut State,
element: &super::OnvifMetadataOverlay,
shapes: Vec<Shape>,
) {
fn overlay_shapes(&self, state: &mut State, shapes: Vec<Shape>) {
if shapes.is_empty() {
state.composition = None;
return;
@ -306,8 +298,8 @@ impl OnvifMetadataOverlay {
let fontmap = match pangocairo::FontMap::new() {
Some(fontmap) => Ok(fontmap),
None => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::LibraryError::Failed,
["Failed to create pangocairo font map"]
);
@ -318,8 +310,8 @@ impl OnvifMetadataOverlay {
let context = match fontmap.create_context() {
Some(context) => Ok(context),
None => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::LibraryError::Failed,
["Failed to create font map context"]
);
@ -348,7 +340,7 @@ impl OnvifMetadataOverlay {
gst::debug!(
CAT,
obj: element,
imp: self,
"Rendering shape with tag {:?} x {} y {} width {} height {}",
shape.tag,
shape.x,
@ -366,7 +358,7 @@ impl OnvifMetadataOverlay {
) {
Some(ret) => ret,
None => {
gst::error!(CAT, obj: element, "Failed to render buffer");
gst::error!(CAT, imp: self, "Failed to render buffer");
state.composition = None;
return;
}
@ -390,13 +382,12 @@ impl OnvifMetadataOverlay {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::OnvifMetadataOverlay,
mut buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::trace!(CAT, obj: pad, "Handling buffer {:?}", buffer);
if self.srcpad.check_reconfigure() {
if let Err(err) = self.negotiate(element) {
if let Err(err) = self.negotiate() {
if self.srcpad.pad_flags().contains(gst::PadFlags::FLUSHING) {
self.srcpad.mark_reconfigure();
return Ok(gst::FlowSuccess::Ok);
@ -417,7 +408,7 @@ impl OnvifMetadataOverlay {
let mut shapes: Vec<Shape> = Vec::new();
if let Ok(frames) = s.get::<gst::BufferList>("frames") {
gst::log!(CAT, obj: element, "Overlaying {} frames", frames.len());
gst::log!(CAT, imp: self, "Overlaying {} frames", frames.len());
// Metadata for multiple frames may be attached to this frame, either because:
//
@ -435,8 +426,8 @@ impl OnvifMetadataOverlay {
for buffer in frames.iter().rev() {
let buffer = buffer.map_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to map buffer readable"]
);
@ -445,8 +436,8 @@ impl OnvifMetadataOverlay {
})?;
let utf8 = std::str::from_utf8(buffer.as_ref()).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Failed to decode buffer as UTF-8: {}", err]
);
@ -455,8 +446,8 @@ impl OnvifMetadataOverlay {
})?;
let root = utf8.parse::<Element>().map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to parse buffer as XML: {}", err]
);
@ -472,14 +463,14 @@ impl OnvifMetadataOverlay {
if object.is("Frame", "http://www.onvif.org/ver10/schema") {
for object in object.children() {
if object.is("Object", "http://www.onvif.org/ver10/schema") {
gst::trace!(CAT, obj: element, "Handling object {:?}", object);
gst::trace!(CAT, imp: self, "Handling object {:?}", object);
let object_id = match object.attr("ObjectId") {
Some(id) => id.to_string(),
None => {
gst::warning!(
CAT,
obj: element,
imp: self,
"XML Object with no ObjectId"
);
continue;
@ -528,7 +519,7 @@ impl OnvifMetadataOverlay {
None => {
gst::warning!(
CAT,
obj: element,
imp: self,
"XML Shape with no BoundingBox"
);
continue;
@ -541,7 +532,7 @@ impl OnvifMetadataOverlay {
None => {
gst::warning!(
CAT,
obj: element,
imp: self,
"BoundingBox with no left attribute"
);
continue;
@ -554,7 +545,7 @@ impl OnvifMetadataOverlay {
None => {
gst::warning!(
CAT,
obj: element,
imp: self,
"BoundingBox with no right attribute"
);
continue;
@ -567,7 +558,7 @@ impl OnvifMetadataOverlay {
None => {
gst::warning!(
CAT,
obj: element,
imp: self,
"BoundingBox with no top attribute"
);
continue;
@ -582,7 +573,7 @@ impl OnvifMetadataOverlay {
None => {
gst::warning!(
CAT,
obj: element,
imp: self,
"BoundingBox with no bottom attribute"
);
continue;
@ -614,7 +605,7 @@ impl OnvifMetadataOverlay {
None => {
gst::warning!(
CAT,
obj: element,
imp: self,
"Point with no x attribute"
);
continue;
@ -629,7 +620,7 @@ impl OnvifMetadataOverlay {
None => {
gst::warning!(
CAT,
obj: element,
imp: self,
"Point with no y attribute"
);
continue;
@ -666,7 +657,7 @@ impl OnvifMetadataOverlay {
}
if !frames.is_empty() {
self.overlay_shapes(&mut state, element, shapes);
self.overlay_shapes(&mut state, shapes);
}
}
}
@ -692,12 +683,7 @@ impl OnvifMetadataOverlay {
self.srcpad.push(buffer)
}
fn sink_event(
&self,
pad: &gst::Pad,
element: &super::OnvifMetadataOverlay,
event: gst::Event,
) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -708,7 +694,7 @@ impl OnvifMetadataOverlay {
state.video_info = gst_video::VideoInfo::from_caps(c.caps()).ok();
drop(state);
self.srcpad.check_reconfigure();
match self.negotiate(element) {
match self.negotiate() {
Ok(_) => true,
Err(_) => {
self.srcpad.mark_reconfigure();
@ -719,9 +705,9 @@ impl OnvifMetadataOverlay {
EventView::FlushStop(..) => {
let mut state = self.state.lock().unwrap();
state.composition = None;
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
}
@ -739,14 +725,14 @@ impl ObjectSubclass for OnvifMetadataOverlay {
OnvifMetadataOverlay::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|overlay, element| overlay.sink_chain(pad, element, buffer),
|overlay| overlay.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
OnvifMetadataOverlay::catch_panic_pad_function(
parent,
|| false,
|overlay, element| overlay.sink_event(pad, element, event),
|overlay| overlay.sink_event(pad, event),
)
})
.flags(gst::PadFlags::PROXY_CAPS)
@ -781,13 +767,7 @@ impl ObjectImpl for OnvifMetadataOverlay {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"font-desc" => {
self.settings.lock().unwrap().font_desc = value
@ -800,16 +780,17 @@ impl ObjectImpl for OnvifMetadataOverlay {
};
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"font-desc" => self.settings.lock().unwrap().font_desc.to_value(),
_ => unimplemented!(),
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -862,10 +843,9 @@ impl ElementImpl for OnvifMetadataOverlay {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused | gst::StateChange::PausedToReady => {
@ -876,6 +856,6 @@ impl ElementImpl for OnvifMetadataOverlay {
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -164,7 +164,6 @@ impl OnvifMetadataParse {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::OnvifMetadataParse,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(
@ -192,7 +191,7 @@ impl OnvifMetadataParse {
.position()
.map_or(true, |position| position < pts)
{
gst::trace!(CAT, obj: element, "Input position updated to {}", pts);
gst::trace!(CAT, imp: self, "Input position updated to {}", pts);
state.in_segment.set_position(pts);
}
@ -299,8 +298,8 @@ impl OnvifMetadataParse {
}
assert!(state.utc_time_running_time_mapping.is_some());
self.queue(element, &mut state, buffer, running_time)?;
let res = self.wake_up_output(element, state);
self.queue(&mut state, buffer, running_time)?;
let res = self.wake_up_output(state);
gst::trace!(CAT, obj: pad, "Returning {:?}", res);
@ -309,7 +308,6 @@ impl OnvifMetadataParse {
fn queue(
&self,
element: &super::OnvifMetadataParse,
state: &mut State,
buffer: gst::Buffer,
running_time: gst::Signed<gst::ClockTime>,
@ -348,14 +346,14 @@ impl OnvifMetadataParse {
};
let root = crate::xml_from_buffer(&buffer).map_err(|err| {
element.post_error_message(err);
self.post_error_message(err);
gst::FlowError::Error
})?;
for res in crate::iterate_video_analytics_frames(&root) {
let (dt, el) = res.map_err(|err| {
element.post_error_message(err);
self.post_error_message(err);
gst::FlowError::Error
})?;
@ -365,7 +363,7 @@ impl OnvifMetadataParse {
gst::trace!(
CAT,
obj: element,
imp: self,
"Queueing frame with UTC time {}",
dt_unix_ns
);
@ -402,13 +400,12 @@ impl OnvifMetadataParse {
fn wake_up_output<'a>(
&'a self,
element: &super::OnvifMetadataParse,
mut state: std::sync::MutexGuard<'a, State>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
if state.upstream_latency.is_none() {
drop(state);
gst::debug!(CAT, obj: element, "Have no upstream latency yet, querying");
gst::debug!(CAT, imp: self, "Have no upstream latency yet, querying");
let mut q = gst::query::Latency::new();
let res = self.sinkpad.peer_query(&mut q);
@ -419,7 +416,7 @@ impl OnvifMetadataParse {
gst::debug!(
CAT,
obj: element,
imp: self,
"Latency query response: live {} min {} max {}",
live,
min,
@ -430,7 +427,7 @@ impl OnvifMetadataParse {
} else {
gst::warning!(
CAT,
obj: element,
imp: self,
"Can't query upstream latency -- assuming non-live upstream for now"
);
}
@ -438,25 +435,25 @@ impl OnvifMetadataParse {
// Consider waking up the source element thread
if self.sinkpad.pad_flags().contains(gst::PadFlags::EOS) {
gst::trace!(CAT, obj: element, "Scheduling immediate wakeup at EOS",);
gst::trace!(CAT, imp: self, "Scheduling immediate wakeup at EOS",);
if let Some(clock_wait) = state.clock_wait.take() {
clock_wait.unschedule();
}
self.cond.notify_all();
} else if self.reschedule_clock_wait(element, &mut state) {
} else if self.reschedule_clock_wait(&mut state) {
self.cond.notify_all();
} else {
// Not live or have no clock
// Wake up if between now and the earliest frame's running time more than the
// configured latency has passed.
let queued_time = self.calculate_queued_time(element, &state);
let queued_time = self.calculate_queued_time(&state);
if queued_time.map_or(false, |queued_time| queued_time >= state.configured_latency) {
gst::trace!(
CAT,
obj: element,
imp: self,
"Scheduling immediate wakeup -- queued time {}",
queued_time.display()
);
@ -471,11 +468,7 @@ impl OnvifMetadataParse {
state.last_flow_ret
}
fn calculate_queued_time(
&self,
element: &super::OnvifMetadataParse,
state: &State,
) -> Option<gst::ClockTime> {
fn calculate_queued_time(&self, state: &State) -> Option<gst::ClockTime> {
let earliest_utc_time = match state.queued_frames.iter().next() {
Some((&earliest_utc_time, _earliest_frame)) => earliest_utc_time,
None => return None,
@ -497,21 +490,12 @@ impl OnvifMetadataParse {
.and_then(|queued_time| queued_time.positive())
.unwrap_or(gst::ClockTime::ZERO);
gst::trace!(
CAT,
obj: element,
"Currently queued {}",
queued_time.display()
);
gst::trace!(CAT, imp: self, "Currently queued {}", queued_time.display());
Some(queued_time)
}
fn reschedule_clock_wait(
&self,
element: &super::OnvifMetadataParse,
state: &mut State,
) -> bool {
fn reschedule_clock_wait(&self, state: &mut State) -> bool {
let earliest_utc_time = match state.queued_frames.iter().next() {
Some((&earliest_utc_time, _earliest_frame)) => earliest_utc_time,
None => return false,
@ -527,12 +511,12 @@ impl OnvifMetadataParse {
earliest_utc_time,
);
let (clock, base_time) = match (element.clock(), element.base_time()) {
let (clock, base_time) = match (self.instance().clock(), self.instance().base_time()) {
(Some(clock), Some(base_time)) => (clock, base_time),
_ => {
gst::warning!(
CAT,
obj: element,
imp: self,
"Upstream is live but have no clock -- assuming non-live for now"
);
return false;
@ -558,7 +542,7 @@ impl OnvifMetadataParse {
}
gst::trace!(
CAT,
obj: element,
imp: self,
"Scheduling timer for {} / running time {}, now {}",
earliest_clock_time,
earliest_running_time.unwrap().display(),
@ -571,7 +555,7 @@ impl OnvifMetadataParse {
if let Some(clock_wait) = state.clock_wait.take() {
clock_wait.unschedule();
}
gst::trace!(CAT, obj: element, "Scheduling immediate wakeup");
gst::trace!(CAT, imp: self, "Scheduling immediate wakeup");
}
true
@ -579,7 +563,6 @@ impl OnvifMetadataParse {
fn drain(
&self,
element: &super::OnvifMetadataParse,
state: &mut State,
drain_utc_time: Option<gst::ClockTime>,
) -> Result<Vec<BufferOrEvent>, gst::FlowError> {
@ -597,7 +580,7 @@ impl OnvifMetadataParse {
gst::log!(
CAT,
obj: element,
imp: self,
"Draining up to UTC time {} / running time {} from current position {} / running time {}",
drain_utc_time.display(),
drain_utc_time
@ -645,12 +628,7 @@ impl OnvifMetadataParse {
});
segment.set_position(current_position);
gst::debug!(
CAT,
obj: element,
"Configuring output segment {:?}",
segment
);
gst::debug!(CAT, imp: self, "Configuring output segment {:?}", segment);
*out_segment = segment;
@ -672,7 +650,7 @@ impl OnvifMetadataParse {
{
gst::trace!(
CAT,
obj: element,
imp: self,
"Output position updated to {}",
current_position
);
@ -695,7 +673,7 @@ impl OnvifMetadataParse {
match utc_time_to_pts(out_segment, utc_time_running_time_mapping, utc_time) {
Some(frame_pts) => frame_pts,
None => {
gst::warning!(CAT, obj: element, "UTC time {} outside segment", utc_time);
gst::warning!(CAT, imp: self, "UTC time {} outside segment", utc_time);
gst::ClockTime::ZERO
}
};
@ -725,7 +703,7 @@ impl OnvifMetadataParse {
{
gst::warning!(
CAT,
obj: element,
imp: self,
"Dropping frame with UTC time {} / PTS {} that is too late by {} at current position {}",
utc_time,
frame_pts,
@ -741,7 +719,7 @@ impl OnvifMetadataParse {
} else if diff > gst::ClockTime::ZERO {
gst::warning!(
CAT,
obj: element,
imp: self,
"Frame in the past by {} with UTC time {} / PTS {} at current position {}",
diff,
utc_time,
@ -757,12 +735,7 @@ impl OnvifMetadataParse {
.position()
.map_or(true, |position| position < frame_pts)
{
gst::trace!(
CAT,
obj: element,
"Output position updated to {}",
frame_pts
);
gst::trace!(CAT, imp: self, "Output position updated to {}", frame_pts);
out_segment.set_position(frame_pts);
}
@ -774,7 +747,7 @@ impl OnvifMetadataParse {
gst::trace!(
CAT,
obj: element,
imp: self,
"Producing frame with UTC time {} / PTS {}",
utc_time,
frame_pts
@ -795,7 +768,7 @@ impl OnvifMetadataParse {
let mut vec = Vec::new();
if let Err(err) = xml.write_to_decl(&mut vec) {
gst::error!(CAT, obj: element, "Can't serialize XML element: {}", err);
gst::error!(CAT, imp: self, "Can't serialize XML element: {}", err);
for event in eos_events {
data.push(BufferOrEvent::Event(event));
}
@ -822,25 +795,20 @@ impl OnvifMetadataParse {
gst::trace!(
CAT,
obj: element,
imp: self,
"Position after draining {} / running time {} -- queued now {} / {} items",
out_segment.position().display(),
out_segment
.to_running_time(out_segment.position())
.display(),
self.calculate_queued_time(element, state).display(),
self.calculate_queued_time(state).display(),
state.queued_frames.len(),
);
Ok(data)
}
fn sink_event(
&self,
pad: &gst::Pad,
element: &super::OnvifMetadataParse,
event: gst::Event,
) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() {
@ -853,7 +821,7 @@ impl OnvifMetadataParse {
drop(state);
self.cond.notify_all();
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
gst::EventView::FlushStop(_) => {
let _ = self.srcpad.stop_task();
@ -867,9 +835,9 @@ impl OnvifMetadataParse {
state.out_segment.set_position(gst::ClockTime::NONE);
state.last_flow_ret = Ok(gst::FlowSuccess::Ok);
drop(state);
let mut res = pad.event_default(Some(element), event);
let mut res = pad.event_default(Some(&*self.instance()), event);
if res {
res = Self::src_start_task(element, &self.srcpad).is_ok();
res = self.src_start_task().is_ok();
}
res
}
@ -880,7 +848,7 @@ impl OnvifMetadataParse {
gst::EventView::StreamStart(_) => {
// Start task again if needed in case we previously went EOS and paused the
// task because of that.
let _ = Self::src_start_task(element, &self.srcpad);
let _ = self.src_start_task();
}
gst::EventView::Segment(ev) => {
match ev.segment().downcast_ref::<gst::ClockTime>().cloned() {
@ -930,8 +898,9 @@ impl OnvifMetadataParse {
gst::debug!(CAT, obj: pad, "Configuring latency of {}", latency);
if previous_latency != latency {
let element = self.instance();
let _ = element.post_message(
gst::message::Latency::builder().src(element).build(),
gst::message::Latency::builder().src(&*element).build(),
);
}
@ -950,7 +919,7 @@ impl OnvifMetadataParse {
{
gst::trace!(
CAT,
obj: element,
imp: self,
"Input position updated to {}",
current_position
);
@ -976,7 +945,7 @@ impl OnvifMetadataParse {
gst::trace!(
CAT,
obj: element,
imp: self,
"Queueing EOS event with UTC time {} / running time {}",
eos_utc_time,
utc_time_to_running_time(*utc_time_running_time_mapping, eos_utc_time)
@ -996,7 +965,7 @@ impl OnvifMetadataParse {
gst::trace!(
CAT,
obj: element,
imp: self,
"Queueing event with UTC time {} / running time {}",
current_utc_time,
current_running_time.display(),
@ -1009,20 +978,20 @@ impl OnvifMetadataParse {
frame.events.push(event);
self.wake_up_output(element, state).is_ok()
self.wake_up_output(state).is_ok()
} else {
if matches!(ev, gst::EventView::Eos(_)) {
gst::error!(
CAT,
obj: element,
imp: self,
"Got EOS event before creating UTC/running time mapping"
);
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Failed,
["Got EOS event before creating UTC/running time mapping"]
);
return pad.event_default(Some(element), event);
return pad.event_default(Some(&*self.instance()), event);
}
let current_running_time = in_segment
@ -1031,7 +1000,7 @@ impl OnvifMetadataParse {
gst::trace!(
CAT,
obj: element,
imp: self,
"Pre-queueing event with running time {}",
current_running_time.display()
);
@ -1040,16 +1009,11 @@ impl OnvifMetadataParse {
true
}
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn sink_query(
&self,
pad: &gst::Pad,
element: &super::OnvifMetadataParse,
query: &mut gst::QueryRef,
) -> bool {
fn sink_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
match query.view_mut() {
@ -1076,16 +1040,11 @@ impl OnvifMetadataParse {
gst::fixme!(CAT, obj: pad, "Dropping allocation query");
false
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
fn src_event(
&self,
pad: &gst::Pad,
element: &super::OnvifMetadataParse,
event: gst::Event,
) -> bool {
fn src_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() {
@ -1098,7 +1057,7 @@ impl OnvifMetadataParse {
drop(state);
self.cond.notify_all();
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
gst::EventView::FlushStop(_) => {
let _ = self.srcpad.stop_task();
@ -1112,22 +1071,17 @@ impl OnvifMetadataParse {
state.out_segment.set_position(gst::ClockTime::NONE);
state.last_flow_ret = Ok(gst::FlowSuccess::Ok);
drop(state);
let mut res = pad.event_default(Some(element), event);
let mut res = pad.event_default(Some(&*self.instance()), event);
if res {
res = Self::src_start_task(element, &self.srcpad).is_ok();
res = self.src_start_task().is_ok();
}
res
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::OnvifMetadataParse,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
match query.view_mut() {
@ -1173,49 +1127,46 @@ impl OnvifMetadataParse {
max.display()
);
let _ = self.wake_up_output(element, state);
let _ = self.wake_up_output(state);
}
ret
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
fn src_start_task(
element: &super::OnvifMetadataParse,
pad: &gst::Pad,
) -> Result<(), gst::LoggableError> {
let element = element.clone();
pad.start_task(move || {
let self_ = element.imp();
if let Err(err) = self_.src_loop(&element) {
match err {
gst::FlowError::Flushing => {
gst::debug!(CAT, obj: &element, "Pausing after flow {:?}", err);
}
gst::FlowError::Eos => {
let _ = self_.srcpad.push_event(gst::event::Eos::builder().build());
fn src_start_task(&self) -> Result<(), gst::LoggableError> {
let self_ = self.ref_counted();
self.srcpad
.start_task(move || {
if let Err(err) = self_.src_loop() {
match err {
gst::FlowError::Flushing => {
gst::debug!(CAT, imp: self_, "Pausing after flow {:?}", err);
}
gst::FlowError::Eos => {
let _ = self_.srcpad.push_event(gst::event::Eos::builder().build());
gst::debug!(CAT, obj: &element, "Pausing after flow {:?}", err);
}
_ => {
let _ = self_.srcpad.push_event(gst::event::Eos::builder().build());
gst::debug!(CAT, imp: self_, "Pausing after flow {:?}", err);
}
_ => {
let _ = self_.srcpad.push_event(gst::event::Eos::builder().build());
gst::error!(CAT, obj: &element, "Pausing after flow {:?}", err);
gst::error!(CAT, imp: self_, "Pausing after flow {:?}", err);
gst::element_error!(
&element,
gst::StreamError::Failed,
["Streaming stopped, reason: {:?}", err]
);
gst::element_imp_error!(
self_,
gst::StreamError::Failed,
["Streaming stopped, reason: {:?}", err]
);
}
}
let _ = self_.srcpad.pause_task();
}
let _ = self_.srcpad.pause_task();
}
})
.map_err(|err| gst::loggable_error!(CAT, "Failed to start pad task: {}", err))
})
.map_err(|err| gst::loggable_error!(CAT, "Failed to start pad task: {}", err))
}
fn src_activatemode(
@ -1230,7 +1181,7 @@ impl OnvifMetadataParse {
if activate {
let element = pad
.parent()
.map(|p| p.downcast::<<Self as ObjectSubclass>::Type>().unwrap())
.map(|p| p.downcast::<super::OnvifMetadataParse>().unwrap())
.ok_or_else(|| {
gst::loggable_error!(CAT, "Failed to start pad task: pad has no parent")
})?;
@ -1240,7 +1191,7 @@ impl OnvifMetadataParse {
state.last_flow_ret = Ok(gst::FlowSuccess::Ok);
drop(state);
Self::src_start_task(&element, pad)?;
self_.src_start_task()?;
} else {
let element = pad
.parent()
@ -1265,7 +1216,7 @@ impl OnvifMetadataParse {
Ok(())
}
fn src_loop(&self, element: &super::OnvifMetadataParse) -> Result<(), gst::FlowError> {
fn src_loop(&self) -> Result<(), gst::FlowError> {
let mut state = self.state.lock().unwrap();
// Remember last clock wait time in case we got woken up slightly earlier than the timer
@ -1280,17 +1231,17 @@ impl OnvifMetadataParse {
let mut drain_running_time = None;
if self.sinkpad.pad_flags().contains(gst::PadFlags::EOS) {
// Drain completely
gst::debug!(CAT, obj: element, "Sink pad is EOS, draining");
gst::debug!(CAT, imp: self, "Sink pad is EOS, draining");
} else if let Some((true, min_latency)) = state.upstream_latency {
// Drain until the current clock running time minus the configured latency when
// live
if let Some((now, base_time)) = Option::zip(
element.clock().and_then(|clock| clock.time()),
element.base_time(),
self.instance().clock().and_then(|clock| clock.time()),
self.instance().base_time(),
) {
gst::trace!(
CAT,
obj: element,
imp: self,
"Clock time now {}, last timer was at {} and current timer at {}",
now,
last_clock_wait_time.display(),
@ -1326,7 +1277,7 @@ impl OnvifMetadataParse {
// And drain up to that running time now, or everything if EOS
let data = if self.sinkpad.pad_flags().contains(gst::PadFlags::EOS) {
self.drain(element, &mut state, None)?
self.drain(&mut state, None)?
} else if let Some(drain_utc_time) =
Option::zip(drain_running_time, state.utc_time_running_time_mapping).and_then(
|(drain_running_time, utc_time_running_time_mapping)| {
@ -1334,7 +1285,7 @@ impl OnvifMetadataParse {
},
)
{
self.drain(element, &mut state, Some(drain_utc_time))?
self.drain(&mut state, Some(drain_utc_time))?
} else {
vec![]
};
@ -1344,13 +1295,13 @@ impl OnvifMetadataParse {
if data.is_empty() {
if self.sinkpad.pad_flags().contains(gst::PadFlags::EOS) {
state.last_flow_ret = Err(gst::FlowError::Eos);
gst::debug!(CAT, obj: element, "EOS, waiting on cond");
gst::debug!(CAT, imp: self, "EOS, waiting on cond");
state = self.cond.wait(state).unwrap();
gst::trace!(CAT, obj: element, "Woke up");
gst::trace!(CAT, imp: self, "Woke up");
} else if let Some(clock_wait) = state.clock_wait.clone() {
gst::trace!(
CAT,
obj: element,
imp: self,
"Waiting on timer with time {}, now {}",
clock_wait.time(),
clock_wait.clock().and_then(|clock| clock.time()).display(),
@ -1369,13 +1320,13 @@ impl OnvifMetadataParse {
match res {
(Ok(_), jitter) => {
gst::trace!(CAT, obj: element, "Woke up after waiting for {}", jitter);
gst::trace!(CAT, imp: self, "Woke up after waiting for {}", jitter);
last_clock_wait_time = Some(clock_wait.time());
}
(Err(err), jitter) => {
gst::trace!(
CAT,
obj: element,
imp: self,
"Woke up with error {:?} and jitter {}",
err,
jitter
@ -1383,9 +1334,9 @@ impl OnvifMetadataParse {
}
}
} else {
gst::debug!(CAT, obj: element, "Waiting on cond");
gst::debug!(CAT, imp: self, "Waiting on cond");
state = self.cond.wait(state).unwrap();
gst::trace!(CAT, obj: element, "Woke up");
gst::trace!(CAT, imp: self, "Woke up");
}
// And retry if there's anything to drain now.
@ -1396,15 +1347,15 @@ impl OnvifMetadataParse {
let mut res = Ok(());
gst::trace!(CAT, obj: element, "Pushing {} items downstream", data.len());
gst::trace!(CAT, imp: self, "Pushing {} items downstream", data.len());
for data in data {
match data {
BufferOrEvent::Event(event) => {
gst::trace!(CAT, obj: element, "Pushing event {:?}", event);
gst::trace!(CAT, imp: self, "Pushing event {:?}", event);
self.srcpad.push_event(event);
}
BufferOrEvent::Buffer(buffer) => {
gst::trace!(CAT, obj: element, "Pushing buffer {:?}", buffer);
gst::trace!(CAT, imp: self, "Pushing buffer {:?}", buffer);
if let Err(err) = self.srcpad.push(buffer) {
res = Err(err);
break;
@ -1412,7 +1363,7 @@ impl OnvifMetadataParse {
}
}
}
gst::trace!(CAT, obj: element, "Pushing returned {:?}", res);
gst::trace!(CAT, imp: self, "Pushing returned {:?}", res);
state = self.state.lock().unwrap();
// If flushing or any other error then just return here
@ -1422,7 +1373,7 @@ impl OnvifMetadataParse {
// Schedule a new clock wait now that data was drained in case we have to wait some
// more time into the future on the next iteration
self.reschedule_clock_wait(element, &mut state);
self.reschedule_clock_wait(&mut state);
// Loop and check if more data has to be drained now
}
@ -1442,21 +1393,21 @@ impl ObjectSubclass for OnvifMetadataParse {
OnvifMetadataParse::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|parse, element| parse.sink_chain(pad, element, buffer),
|parse| parse.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
OnvifMetadataParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.sink_event(pad, element, event),
|parse| parse.sink_event(pad, event),
)
})
.query_function(|pad, parent, query| {
OnvifMetadataParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.sink_query(pad, element, query),
|parse| parse.sink_query(pad, query),
)
})
.flags(gst::PadFlags::PROXY_ALLOCATION)
@ -1468,14 +1419,14 @@ impl ObjectSubclass for OnvifMetadataParse {
OnvifMetadataParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_event(pad, element, event),
|parse| parse.src_event(pad, event),
)
})
.query_function(|pad, parent, query| {
OnvifMetadataParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_query(pad, element, query),
|parse| parse.src_query(pad, query),
)
})
.activatemode_function(|pad, _parent, mode, activate| {
@ -1530,18 +1481,16 @@ impl ObjectImpl for OnvifMetadataParse {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"latency" => {
self.settings.lock().unwrap().latency = value.get().expect("type checked upstream");
let _ = obj.post_message(gst::message::Latency::builder().src(obj).build());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
}
"max-lateness" => {
self.settings.lock().unwrap().max_lateness =
@ -1551,7 +1500,7 @@ impl ObjectImpl for OnvifMetadataParse {
};
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"latency" => self.settings.lock().unwrap().latency.to_value(),
"max-lateness" => self.settings.lock().unwrap().max_lateness.to_value(),
@ -1559,9 +1508,10 @@ impl ObjectImpl for OnvifMetadataParse {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -1613,10 +1563,9 @@ impl ElementImpl for OnvifMetadataParse {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
if matches!(
transition,
@ -1626,6 +1575,6 @@ impl ElementImpl for OnvifMetadataParse {
*state = State::default();
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -65,18 +65,14 @@ impl ElementImpl for OnvifMetadataPay {
}
impl RTPBasePayloadImpl for OnvifMetadataPay {
fn handle_buffer(
&self,
element: &Self::Type,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
fn handle_buffer(&self, buffer: gst::Buffer) -> Result<gst::FlowSuccess, gst::FlowError> {
let pts = buffer.pts();
let dts = buffer.dts();
// Input buffer must be readable
let buffer = buffer.into_mapped_buffer_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to map buffer readable"]
);
@ -86,8 +82,8 @@ impl RTPBasePayloadImpl for OnvifMetadataPay {
// Input buffer must be valid UTF-8
let utf8 = std::str::from_utf8(buffer.as_ref()).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Failed to decode buffer as UTF-8: {}", err]
);
@ -120,8 +116,8 @@ impl RTPBasePayloadImpl for OnvifMetadataPay {
}
},
Err(err) => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Invalid XML: {}", err]
);
@ -135,8 +131,8 @@ impl RTPBasePayloadImpl for OnvifMetadataPay {
};
if !process {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["document must start with tt:MetadataStream element"]
);
@ -144,7 +140,7 @@ impl RTPBasePayloadImpl for OnvifMetadataPay {
return Err(gst::FlowError::Error);
}
let mtu = element.mtu();
let mtu = self.instance().mtu();
let payload_size = gst_rtp::RTPBuffer::<()>::calc_payload_len(mtu, 0, 0) as usize;
let mut chunks = utf8.as_bytes().chunks(payload_size).peekable();
@ -156,8 +152,8 @@ impl RTPBasePayloadImpl for OnvifMetadataPay {
while let Some(chunk) = chunks.next() {
let mut outbuf = gst::Buffer::new_rtp_with_sizes(chunk.len() as u32, 0, 0)
.map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Write,
["Failed to allocate output buffer: {}", err]
);
@ -184,11 +180,12 @@ impl RTPBasePayloadImpl for OnvifMetadataPay {
}
}
element.push_list(buflist)
self.instance().push_list(buflist)
}
fn set_caps(&self, element: &Self::Type, _caps: &gst::Caps) -> Result<(), gst::LoggableError> {
element.set_options("application", true, "VND.ONVIF.METADATA", 90000);
fn set_caps(&self, _caps: &gst::Caps) -> Result<(), gst::LoggableError> {
self.instance()
.set_options("application", true, "VND.ONVIF.METADATA", 90000);
Ok(())
}

View file

@ -146,11 +146,7 @@ pub struct RaptorqDec {
}
impl RaptorqDec {
fn process_source_block(
&self,
element: &super::RaptorqDec,
state: &mut State,
) -> Result<gst::FlowSuccess, gst::FlowError> {
fn process_source_block(&self, state: &mut State) -> Result<gst::FlowSuccess, gst::FlowError> {
// Pull the information about the current Source Block from sequence.
// Data packets for current Source Block are in range: info.seq_range(),
// Repair Packets on the other hand, for a given block share the same key
@ -169,7 +165,7 @@ impl RaptorqDec {
if data_packets_num == n {
gst::trace!(
CAT,
obj: element,
imp: self,
"All packets ({}) received, dropping Source Block ({})",
data_packets_num,
seq_lo
@ -304,7 +300,7 @@ impl RaptorqDec {
gst::debug!(
CAT,
obj: element,
imp: self,
"Succesfully recovered packet: seqnum: {}, len: {}, ts: {}",
rtpbuf.seq(),
rtpbuf.payload_size(),
@ -323,19 +319,18 @@ impl RaptorqDec {
fn store_media_packet(
&self,
element: &super::RaptorqDec,
state: &mut State,
buffer: &gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let this_seq = {
let rtpbuf = RTPBuffer::from_buffer_readable(buffer).map_err(|err| {
gst::error!(CAT, obj: element, "Failed to map rtp buffer : {}", err);
gst::error!(CAT, imp: self, "Failed to map rtp buffer : {}", err);
gst::FlowError::Error
})?;
gst::trace!(
CAT,
obj: element,
imp: self,
"New data packet, seq {}, ts {}",
rtpbuf.seq(),
rtpbuf.timestamp()
@ -383,18 +378,17 @@ impl RaptorqDec {
fn sink_chain(
&self,
_pad: &gst::Pad,
element: &super::RaptorqDec,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state = self.state.lock().unwrap();
self.store_media_packet(element, &mut state, &buffer)?;
self.store_media_packet(&mut state, &buffer)?;
// Retire the packets that have been around for too long
let expired = state.expire_packets();
for seq in expired {
gst::trace!(
CAT,
obj: element,
imp: self,
"Source Block ({}) dropped, because max wait time has been exceeded",
seq as u16
);
@ -405,16 +399,16 @@ impl RaptorqDec {
if thresh > 0 && state.media_packets.len() >= thresh {
gst::warning!(
CAT,
obj: element,
imp: self,
"Too many buffered media packets, resetting decoder. This might \
be because we haven't received a repair packet for too long, or \
repair packets have no valid timestamps.",
);
self.reset(element);
self.reset();
}
self.process_source_block(element, &mut state)?;
self.process_source_block(&mut state)?;
drop(state);
self.srcpad.push(buffer)
@ -423,17 +417,16 @@ impl RaptorqDec {
fn fec_sink_chain(
&self,
_pad: &gst::Pad,
element: &super::RaptorqDec,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let rtpbuf = RTPBuffer::from_buffer_readable(&buffer).map_err(|err| {
gst::error!(CAT, obj: element, "Failed to map rtp buffer : {}", err);
gst::error!(CAT, imp: self, "Failed to map rtp buffer : {}", err);
gst::FlowError::Error
})?;
let payload = rtpbuf.payload().unwrap();
let payload_id = payload[0..7].try_into().map_err(|err| {
gst::error!(CAT, obj: element, "Unexpected rtp fec payload : {}", err);
gst::error!(CAT, imp: self, "Unexpected rtp fec payload : {}", err);
gst::FlowError::Error
})?;
@ -447,7 +440,7 @@ impl RaptorqDec {
gst::trace!(
CAT,
obj: element,
imp: self,
"New repair packet, I: {}, LP: {}, LB: {}",
i,
lp,
@ -496,30 +489,25 @@ impl RaptorqDec {
Ok(gst::FlowSuccess::Ok)
}
fn sink_event(&self, pad: &gst::Pad, element: &super::RaptorqDec, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
gst::debug!(CAT, "Handling event {:?}", event);
use gst::EventView;
if let EventView::FlushStop(_) = event.view() {
self.reset(element);
self.reset();
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
fn fec_sink_event(
&self,
pad: &gst::Pad,
element: &super::RaptorqDec,
event: gst::Event,
) -> bool {
fn fec_sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
gst::debug!(CAT, "Handling event {:?}", event);
use gst::EventView;
if let EventView::Caps(c) = event.view() {
if let Err(err) = self.start(element, c.caps()) {
gst::element_error!(
element,
if let Err(err) = self.start(c.caps()) {
gst::element_imp_error!(
self,
gst::CoreError::Event,
["Failed to start raptorqdec {:?}", err]
);
@ -528,14 +516,10 @@ impl RaptorqDec {
}
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
fn iterate_internal_links(
&self,
pad: &gst::Pad,
_element: &super::RaptorqDec,
) -> gst::Iterator<gst::Pad> {
fn iterate_internal_links(&self, pad: &gst::Pad) -> gst::Iterator<gst::Pad> {
if pad == &self.srcpad {
gst::Iterator::from_vec(vec![self.sinkpad.clone()])
} else if pad == &self.sinkpad {
@ -545,21 +529,17 @@ impl RaptorqDec {
}
}
fn start(
&self,
element: &super::RaptorqDec,
incaps: &gst::CapsRef,
) -> Result<(), gst::ErrorMessage> {
fn start(&self, incaps: &gst::CapsRef) -> Result<(), gst::ErrorMessage> {
let symbol_size = fmtp_param_from_caps::<usize>("t", incaps)?;
if symbol_size > fecscheme::MAX_ENCODING_SYMBOL_SIZE {
let details = format!(
"Symbol size exceeds Maximum Encoding Symbol Size: {}",
fecscheme::MAX_ENCODING_SYMBOL_SIZE
);
gst::element_error!(element, gst::CoreError::Failed, [&details]);
return Err(error_msg!(gst::CoreError::Failed, [&details]));
return Err(error_msg!(
gst::CoreError::Failed,
[
"Symbol size exceeds Maximum Encoding Symbol Size: {}",
fecscheme::MAX_ENCODING_SYMBOL_SIZE
]
));
}
let settings = self.settings.lock().unwrap();
@ -573,7 +553,7 @@ impl RaptorqDec {
let media_packets_reset_threshold = settings.media_packets_reset_threshold as usize;
gst::debug!(CAT, obj: element, "Configured for caps {}", incaps);
gst::debug!(CAT, imp: self, "Configured for caps {}", incaps);
let mut state = self.state.lock().unwrap();
@ -584,11 +564,11 @@ impl RaptorqDec {
Ok(())
}
fn stop(&self, element: &super::RaptorqDec) {
self.reset(element);
fn stop(&self) {
self.reset();
}
fn reset(&self, _element: &super::RaptorqDec) {
fn reset(&self) {
let mut state = self.state.lock().unwrap();
state.media_packets.clear();
@ -615,21 +595,17 @@ impl ObjectSubclass for RaptorqDec {
Self::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
|this| this.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
Self::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
)
Self::catch_panic_pad_function(parent, || false, |this| this.sink_event(pad, event))
})
.iterate_internal_links_function(|pad, parent| {
Self::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|this, element| this.iterate_internal_links(pad, element),
|this| this.iterate_internal_links(pad),
)
})
.flags(gst::PadFlags::PROXY_CAPS)
@ -641,7 +617,7 @@ impl ObjectSubclass for RaptorqDec {
Self::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|this, element| this.iterate_internal_links(pad, element),
|this| this.iterate_internal_links(pad),
)
})
.flags(gst::PadFlags::PROXY_CAPS)
@ -688,13 +664,7 @@ impl ObjectImpl for RaptorqDec {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"repair-window-tolerance" => {
let mut settings = self.settings.lock().unwrap();
@ -711,7 +681,7 @@ impl ObjectImpl for RaptorqDec {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"repair-window-tolerance" => {
let settings = self.settings.lock().unwrap();
@ -746,9 +716,10 @@ impl ObjectImpl for RaptorqDec {
_ => unimplemented!(),
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -815,27 +786,25 @@ impl ElementImpl for RaptorqDec {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused => {
self.reset(element);
self.reset();
}
gst::StateChange::PausedToReady => {
self.stop(element);
self.stop();
}
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
fn request_new_pad(
&self,
element: &Self::Type,
templ: &gst::PadTemplate,
name: Option<String>,
_caps: Option<&gst::Caps>,
@ -843,8 +812,8 @@ impl ElementImpl for RaptorqDec {
let mut sinkpad_fec_guard = self.sinkpad_fec.lock().unwrap();
if sinkpad_fec_guard.is_some() {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Pad,
["Not accepting more than one FEC stream"]
);
@ -857,21 +826,21 @@ impl ElementImpl for RaptorqDec {
Self::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.fec_sink_chain(pad, element, buffer),
|this| this.fec_sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
Self::catch_panic_pad_function(
parent,
|| false,
|this, element| this.fec_sink_event(pad, element, event),
|this| this.fec_sink_event(pad, event),
)
})
.iterate_internal_links_function(|pad, parent| {
Self::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|this, element| this.iterate_internal_links(pad, element),
|this| this.iterate_internal_links(pad),
)
})
.build();
@ -881,18 +850,18 @@ impl ElementImpl for RaptorqDec {
drop(sinkpad_fec_guard);
element.add_pad(&sinkpad_fec).unwrap();
self.instance().add_pad(&sinkpad_fec).unwrap();
Some(sinkpad_fec)
}
fn release_pad(&self, element: &Self::Type, _pad: &gst::Pad) {
fn release_pad(&self, _pad: &gst::Pad) {
let mut pad_guard = self.sinkpad_fec.lock().unwrap();
if let Some(pad) = pad_guard.take() {
drop(pad_guard);
pad.set_active(false).unwrap();
element.remove_pad(&pad).unwrap();
self.instance().remove_pad(&pad).unwrap();
}
}
}

View file

@ -4,7 +4,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
use gst::{element_error, error_msg, glib, loggable_error};
use gst::{element_imp_error, error_msg, glib, loggable_error};
use gst::prelude::*;
use gst::subclass::prelude::*;
@ -105,7 +105,7 @@ pub struct RaptorqEnc {
impl RaptorqEnc {
fn process_source_block(
element: &super::RaptorqEnc,
&self,
state: &mut State,
now_pts: Option<gst::ClockTime>,
now_dts: Option<gst::ClockTime>,
@ -132,13 +132,7 @@ impl RaptorqEnc {
// placed in each repair packet.
let si = state.symbols_per_packet;
gst::trace!(
CAT,
obj: element,
"Source Block add ADU: si {}, li {}",
si,
li
);
gst::trace!(CAT, imp: self, "Source Block add ADU: si {}, li {}", si, li);
let mut data = vec![0; si * state.symbol_size];
@ -186,7 +180,7 @@ impl RaptorqEnc {
.map(|n| gst::ClockTime::from_mseconds((n * delay_step) as u64))
.collect::<Vec<_>>();
let base_time = element.base_time();
let base_time = self.instance().base_time();
let running_time = state.segment.to_running_time(now_pts);
for (target_time, repair_packet) in Iterator::zip(
@ -261,7 +255,7 @@ impl RaptorqEnc {
Ok(gst::FlowSuccess::Ok)
}
fn start_task(&self, element: &super::RaptorqEnc) -> Result<(), gst::LoggableError> {
fn start_task(&self) -> Result<(), gst::LoggableError> {
let (sender, receiver) = mpsc::channel();
let mut state_guard = self.state.lock().unwrap();
@ -270,36 +264,25 @@ impl RaptorqEnc {
state.sender = Some(sender);
drop(state_guard);
let element_weak = element.downgrade();
let pad_weak = self.srcpad_fec.downgrade();
let self_ = self.ref_counted();
let mut eos = false;
self.srcpad_fec
.start_task(move || {
while let Ok(msg) = receiver.recv() {
let pad = match pad_weak.upgrade() {
Some(pad) => pad,
None => break,
};
let element = match element_weak.upgrade() {
Some(element) => element,
None => break,
};
match msg {
SrcTaskMsg::Timeout((id, buf)) => {
let mut timers = element.imp().pending_timers.lock().unwrap();
let mut timers = self_.pending_timers.lock().unwrap();
let _ = timers.remove(&id);
let push_eos = eos && timers.is_empty();
drop(timers);
if let Err(err) = pad.push(buf) {
gst::element_error!(
element,
if let Err(err) = self_.srcpad_fec.push(buf) {
gst::element_imp_error!(
self_,
gst::CoreError::Pad,
["Failed to push on src FEC pad {:?}", err]
);
@ -308,7 +291,7 @@ impl RaptorqEnc {
}
if push_eos {
pad.push_event(gst::event::Eos::new());
self_.srcpad_fec.push_event(gst::event::Eos::new());
break;
}
}
@ -317,9 +300,9 @@ impl RaptorqEnc {
Some(target) => target,
None => {
// No target, push buffer immediately
if let Err(err) = pad.push(buf) {
gst::element_error!(
element,
if let Err(err) = self_.srcpad_fec.push(buf) {
gst::element_imp_error!(
self_,
gst::CoreError::Pad,
["Failed to push on src FEC pad {:?}", err]
);
@ -330,13 +313,13 @@ impl RaptorqEnc {
}
};
let clock = match element.clock() {
let clock = match self_.instance().clock() {
Some(clock) => clock,
None => {
// No clock provided, push buffer immediately
if let Err(err) = pad.push(buf) {
gst::element_error!(
element,
if let Err(err) = self_.srcpad_fec.push(buf) {
gst::element_imp_error!(
self_,
gst::CoreError::Pad,
["Failed to push on src FEC pad {:?}", err]
);
@ -348,7 +331,7 @@ impl RaptorqEnc {
};
let timeout_sender = {
let state_guard = element.imp().state.lock().unwrap();
let state_guard = self_.state.lock().unwrap();
let state = match state_guard.as_ref() {
Some(state) => state,
None => break,
@ -359,7 +342,7 @@ impl RaptorqEnc {
let timeout = clock.new_single_shot_id(target);
let mut timers = element.imp().pending_timers.lock().unwrap();
let mut timers = self_.pending_timers.lock().unwrap();
timers.insert(timeout.clone().into());
timeout
@ -370,8 +353,8 @@ impl RaptorqEnc {
.expect("Failed to wait async");
}
SrcTaskMsg::Eos => {
if element.imp().pending_timers.lock().unwrap().is_empty() {
pad.push_event(gst::event::Eos::new());
if self_.pending_timers.lock().unwrap().is_empty() {
self_.srcpad_fec.push_event(gst::event::Eos::new());
break;
}
@ -381,12 +364,7 @@ impl RaptorqEnc {
}
// All senders dropped or error
let pad = match pad_weak.upgrade() {
Some(pad) => pad,
None => return,
};
let _ = pad.pause_task();
let _ = self_.srcpad_fec.pause_task();
})
.map_err(|_| loggable_error!(CAT, "Failed to start pad task"))?;
@ -396,12 +374,11 @@ impl RaptorqEnc {
fn src_activatemode(
&self,
_pad: &gst::Pad,
element: &super::RaptorqEnc,
_mode: gst::PadMode,
active: bool,
) -> Result<(), gst::LoggableError> {
if active {
self.start_task(element)?;
self.start_task()?;
} else {
// element stop should be called at this point so that all mpsc
// senders used in task are dropped, otherwise channel can deadlock
@ -414,28 +391,27 @@ impl RaptorqEnc {
fn sink_chain(
&self,
_pad: &gst::Pad,
element: &super::RaptorqEnc,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().ok_or(gst::FlowError::NotNegotiated)?;
if buffer.size() > state.mtu {
gst::error!(CAT, obj: element, "Packet length exceeds configured MTU");
gst::error!(CAT, imp: self, "Packet length exceeds configured MTU");
return Err(gst::FlowError::NotSupported);
}
let (curr_seq, now_rtpts) = match RTPBuffer::from_buffer_readable(&buffer) {
Ok(rtpbuf) => (rtpbuf.seq(), rtpbuf.timestamp()),
Err(_) => {
gst::error!(CAT, obj: element, "Mapping to RTP packet failed");
gst::error!(CAT, imp: self, "Mapping to RTP packet failed");
return Err(gst::FlowError::NotSupported);
}
};
if let Some(last_seq) = state.seqnums.last() {
if last_seq.overflowing_add(1).0 != curr_seq {
gst::error!(CAT, obj: element, "Got out of sequence packets");
gst::error!(CAT, imp: self, "Got out of sequence packets");
return Err(gst::FlowError::NotSupported);
}
}
@ -450,22 +426,22 @@ impl RaptorqEnc {
let now_pts = buffer.pts();
let now_dts = buffer.dts_or_pts();
Self::process_source_block(element, state, now_pts, now_dts, now_rtpts)?;
self.process_source_block(state, now_pts, now_dts, now_rtpts)?;
}
drop(state_guard);
self.srcpad.push(buffer)
}
fn sink_event(&self, pad: &gst::Pad, element: &super::RaptorqEnc, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
gst::debug!(CAT, "Handling event {:?}", event);
use gst::EventView;
match event.view() {
EventView::FlushStart(_) => {
if let Err(err) = self.stop(element) {
element_error!(
element,
if let Err(err) = self.stop() {
element_imp_error!(
self,
gst::CoreError::Event,
["Failed to stop encoder after flush start {:?}", err]
);
@ -475,9 +451,9 @@ impl RaptorqEnc {
let _ = self.srcpad_fec.set_active(false);
}
EventView::FlushStop(_) => {
if let Err(err) = self.start(element) {
element_error!(
element,
if let Err(err) = self.start() {
element_imp_error!(
self,
gst::CoreError::Event,
["Failed to start encoder after flush stop {:?}", err]
);
@ -499,7 +475,7 @@ impl RaptorqEnc {
// delayed repair packets.
if let Ok(clock_rate) = s.get::<i32>("clock-rate") {
if clock_rate <= 0 {
element_error!(element, gst::CoreError::Event, ["Invalid clock rate"]);
element_imp_error!(self, gst::CoreError::Event, ["Invalid clock rate"]);
return false;
}
@ -515,8 +491,8 @@ impl RaptorqEnc {
let segment = match segment.downcast::<gst::ClockTime>() {
Ok(segment) => segment,
Err(_) => {
element_error!(
element,
element_imp_error!(
self,
gst::CoreError::Event,
["Only time segments are supported"]
);
@ -527,8 +503,10 @@ impl RaptorqEnc {
state.segment = segment.clone();
// Push stream events on FEC srcpad as well
let pad = &self.srcpad_fec;
let stream_id = pad.create_stream_id(element, Some("fec")).to_string();
let stream_id = self
.srcpad_fec
.create_stream_id(&*self.instance(), Some("fec"))
.to_string();
let kmax = extended_source_block_symbols(state.symbols_per_block as u32);
let scheme_id = fecscheme::FEC_SCHEME_ID;
@ -548,9 +526,11 @@ impl RaptorqEnc {
drop(state_guard);
pad.push_event(gst::event::StreamStart::new(&stream_id));
pad.push_event(gst::event::Caps::new(&caps));
pad.push_event(gst::event::Segment::new(&segment));
self.srcpad_fec
.push_event(gst::event::StreamStart::new(&stream_id));
self.srcpad_fec.push_event(gst::event::Caps::new(&caps));
self.srcpad_fec
.push_event(gst::event::Segment::new(&segment));
}
}
EventView::Eos(_) => {
@ -563,14 +543,10 @@ impl RaptorqEnc {
_ => (),
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
fn iterate_internal_links(
&self,
pad: &gst::Pad,
_element: &super::RaptorqEnc,
) -> gst::Iterator<gst::Pad> {
fn iterate_internal_links(&self, pad: &gst::Pad) -> gst::Iterator<gst::Pad> {
if pad == &self.sinkpad {
gst::Iterator::from_vec(vec![self.srcpad.clone()])
} else if pad == &self.srcpad {
@ -580,7 +556,7 @@ impl RaptorqEnc {
}
}
fn start(&self, element: &super::RaptorqEnc) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
let settings = self.settings.lock().unwrap();
let protected_packets_num = settings.protected_packets as usize;
@ -598,38 +574,38 @@ impl RaptorqEnc {
let symbols_per_block = symbols_per_packet * protected_packets_num;
if symbol_size.rem_euclid(SYMBOL_ALIGNMENT) != 0 {
let details = format!(
"Symbol size is not multiple of Symbol Alignment {}",
SYMBOL_ALIGNMENT
);
gst::element_error!(element, gst::CoreError::Failed, [&details]);
return Err(error_msg!(gst::CoreError::Failed, [&details]));
return Err(error_msg!(
gst::CoreError::Failed,
[
"Symbol size is not multiple of Symbol Alignment {}",
SYMBOL_ALIGNMENT
]
));
}
if symbol_size > fecscheme::MAX_ENCODING_SYMBOL_SIZE {
let details = format!(
"Symbol size exceeds Maximum Encoding Symbol Size: {}",
fecscheme::MAX_ENCODING_SYMBOL_SIZE
);
gst::element_error!(element, gst::CoreError::Failed, [&details]);
return Err(error_msg!(gst::CoreError::Failed, [&details]));
return Err(error_msg!(
gst::CoreError::Failed,
[
"Symbol size exceeds Maximum Encoding Symbol Size: {}",
fecscheme::MAX_ENCODING_SYMBOL_SIZE
]
));
}
if symbols_per_block > fecscheme::MAX_SOURCE_BLOCK_LEN {
let details = format!(
"Source block length exceeds Maximum Source Block Length: {}",
fecscheme::MAX_SOURCE_BLOCK_LEN
);
gst::element_error!(element, gst::CoreError::Failed, [&details]);
return Err(error_msg!(gst::CoreError::Failed, [&details]));
return Err(error_msg!(
gst::CoreError::Failed,
[
"Source block length exceeds Maximum Source Block Length: {}",
fecscheme::MAX_SOURCE_BLOCK_LEN
]
));
}
gst::info!(
CAT,
obj: element,
imp: self,
"Starting RaptorQ Encoder, Symbols per Block: {}, Symbol Size: {}",
symbols_per_block,
symbol_size
@ -663,7 +639,7 @@ impl RaptorqEnc {
Ok(())
}
fn stop(&self, _element: &super::RaptorqEnc) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
let mut timers = self.pending_timers.lock().unwrap();
for timer in timers.drain() {
timer.unschedule();
@ -688,21 +664,17 @@ impl ObjectSubclass for RaptorqEnc {
Self::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
|this| this.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
Self::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
)
Self::catch_panic_pad_function(parent, || false, |this| this.sink_event(pad, event))
})
.iterate_internal_links_function(|pad, parent| {
Self::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|this, element| this.iterate_internal_links(pad, element),
|this| this.iterate_internal_links(pad),
)
})
.flags(gst::PadFlags::PROXY_CAPS)
@ -714,7 +686,7 @@ impl ObjectSubclass for RaptorqEnc {
Self::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|this, element| this.iterate_internal_links(pad, element),
|this| this.iterate_internal_links(pad),
)
})
.flags(gst::PadFlags::PROXY_CAPS)
@ -726,14 +698,14 @@ impl ObjectSubclass for RaptorqEnc {
Self::catch_panic_pad_function(
parent,
|| Err(loggable_error!(CAT, "Panic activating src pad with mode")),
|this, element| this.src_activatemode(pad, element, mode, active),
|this| this.src_activatemode(pad, mode, active),
)
})
.iterate_internal_links_function(|pad, parent| {
Self::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|this, element| this.iterate_internal_links(pad, element),
|this| this.iterate_internal_links(pad),
)
})
.build();
@ -805,13 +777,7 @@ impl ObjectImpl for RaptorqEnc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"protected-packets" => {
let mut settings = self.settings.lock().unwrap();
@ -847,7 +813,7 @@ impl ObjectImpl for RaptorqEnc {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"protected-packets" => {
let settings = self.settings.lock().unwrap();
@ -877,9 +843,10 @@ impl ObjectImpl for RaptorqEnc {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
obj.add_pad(&self.srcpad_fec).unwrap();
@ -940,21 +907,20 @@ impl ElementImpl for RaptorqEnc {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused => {
self.start(element).map_err(|_| gst::StateChangeError)?;
self.start().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::PausedToReady => {
self.stop(element).map_err(|_| gst::StateChangeError)?;
self.stop().map_err(|_| gst::StateChangeError)?;
}
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -170,11 +170,7 @@ static RUNTIME: Lazy<runtime::Runtime> = Lazy::new(|| {
});
impl ReqwestHttpSrc {
fn set_location(
&self,
_element: &super::ReqwestHttpSrc,
uri: Option<&str>,
) -> Result<(), glib::Error> {
fn set_location(&self, uri: Option<&str>) -> Result<(), glib::Error> {
let state = self.state.lock().unwrap();
if let State::Started { .. } = *state {
return Err(glib::Error::new(
@ -251,37 +247,35 @@ impl ReqwestHttpSrc {
fn ensure_client(
&self,
src: &super::ReqwestHttpSrc,
proxy: Option<String>,
proxy_id: Option<String>,
proxy_pw: Option<String>,
) -> Result<ClientContext, gst::ErrorMessage> {
let mut client_guard = self.client.lock().unwrap();
if let Some(ref client) = *client_guard {
gst::debug!(CAT, obj: src, "Using already configured client");
gst::debug!(CAT, imp: self, "Using already configured client");
return Ok(client.clone());
}
// Attempt to acquire an existing client context from another element instance
// unless using proxy, because proxy is client specific.
if proxy.is_none() {
let srcpad = src.static_pad("src").unwrap();
let mut q = gst::query::Context::new(REQWEST_CLIENT_CONTEXT);
if srcpad.peer_query(&mut q) {
if self.instance().src_pad().peer_query(&mut q) {
if let Some(context) = q.context_owned() {
src.set_context(&context);
self.instance().set_context(&context);
}
} else {
let _ = src.post_message(
let _ = self.instance().post_message(
gst::message::NeedContext::builder(REQWEST_CLIENT_CONTEXT)
.src(src)
.src(&*self.instance())
.build(),
);
}
// Hopefully now, self.set_context will have been synchronously called
if let Some(client) = self.external_client.lock().unwrap().clone() {
gst::debug!(CAT, obj: src, "Using shared client");
gst::debug!(CAT, imp: self, "Using shared client");
*client_guard = Some(client.clone());
return Ok(client);
@ -302,7 +296,7 @@ impl ReqwestHttpSrc {
builder = builder.proxy(p);
}
gst::debug!(CAT, obj: src, "Creating new client");
gst::debug!(CAT, imp: self, "Creating new client");
let client = ClientContext(Arc::new(ClientContextInner {
client: builder.build().map_err(|err| {
gst::error_msg!(
@ -316,15 +310,19 @@ impl ReqwestHttpSrc {
// The alternative would be different contexts for different proxy settings, or one context with a
// map from proxy settings to client, but then, how and when to discard those, retaining reuse benefits?
if proxy.is_none() {
gst::debug!(CAT, obj: src, "Sharing new client with other elements");
gst::debug!(CAT, imp: self, "Sharing new client with other elements");
let mut context = gst::Context::new(REQWEST_CLIENT_CONTEXT, true);
{
let context = context.get_mut().unwrap();
let s = context.structure_mut();
s.set("client", &client);
}
src.set_context(&context);
let _ = src.post_message(gst::message::HaveContext::builder(context).src(src).build());
self.instance().set_context(&context);
let _ = self.instance().post_message(
gst::message::HaveContext::builder(context)
.src(&*self.instance())
.build(),
);
}
*client_guard = Some(client.clone());
@ -334,7 +332,6 @@ impl ReqwestHttpSrc {
fn do_request(
&self,
src: &super::ReqwestHttpSrc,
uri: Url,
start: u64,
stop: Option<u64>,
@ -342,12 +339,12 @@ impl ReqwestHttpSrc {
use headers::{Connection, ContentLength, ContentRange, HeaderMapExt, Range, UserAgent};
use reqwest::header::{self, HeaderMap, HeaderName, HeaderValue};
gst::debug!(CAT, obj: src, "Creating new request for {}", uri);
gst::debug!(CAT, imp: self, "Creating new request for {}", uri);
let settings = self.settings.lock().unwrap().clone();
let req = self
.ensure_client(src, settings.proxy, settings.proxy_id, settings.proxy_pw)?
.ensure_client(settings.proxy, settings.proxy_id, settings.proxy_pw)?
.0
.client
.get(uri.clone());
@ -387,7 +384,7 @@ impl ReqwestHttpSrc {
Err(err) => {
gst::warning!(
CAT,
obj: src,
imp: self,
"Failed to transform extra-header field name '{}' to header name: {}",
field,
err,
@ -403,7 +400,7 @@ impl ReqwestHttpSrc {
Err(_) => {
gst::warning!(
CAT,
obj: src,
imp: self,
"Failed to transform extra-header '{}' value to string",
field
);
@ -418,7 +415,7 @@ impl ReqwestHttpSrc {
Err(_) => {
gst::warning!(
CAT,
obj: src,
imp: self,
"Failed to transform extra-header '{}' value to header value",
field
);
@ -464,7 +461,7 @@ impl ReqwestHttpSrc {
req
};
gst::debug!(CAT, obj: src, "Sending new request: {:?}", req);
gst::debug!(CAT, imp: self, "Sending new request: {:?}", req);
let future = async {
req.send().await.map_err(|err| {
@ -479,21 +476,21 @@ impl ReqwestHttpSrc {
let res = match res {
Ok(res) => res,
Err(Some(err)) => {
gst::debug!(CAT, obj: src, "Error {:?}", err);
gst::debug!(CAT, imp: self, "Error {:?}", err);
return Err(Some(err));
}
Err(None) => {
gst::debug!(CAT, obj: src, "Flushing");
gst::debug!(CAT, imp: self, "Flushing");
return Err(None);
}
};
gst::debug!(CAT, obj: src, "Received response: {:?}", res);
gst::debug!(CAT, imp: self, "Received response: {:?}", res);
if !res.status().is_success() {
match res.status() {
StatusCode::NOT_FOUND => {
gst::error!(CAT, obj: src, "Resource not found");
gst::error!(CAT, imp: self, "Resource not found");
return Err(Some(gst::error_msg!(
gst::ResourceError::NotFound,
["Resource '{}' not found", uri]
@ -503,14 +500,14 @@ impl ReqwestHttpSrc {
| StatusCode::PAYMENT_REQUIRED
| StatusCode::FORBIDDEN
| StatusCode::PROXY_AUTHENTICATION_REQUIRED => {
gst::error!(CAT, obj: src, "Not authorized: {}", res.status());
gst::error!(CAT, imp: self, "Not authorized: {}", res.status());
return Err(Some(gst::error_msg!(
gst::ResourceError::NotAuthorized,
["Not Authorized for resource '{}': {}", uri, res.status()]
)));
}
_ => {
gst::error!(CAT, obj: src, "Request failed: {}", res.status());
gst::error!(CAT, imp: self, "Request failed: {}", res.status());
return Err(Some(gst::error_msg!(
gst::ResourceError::OpenRead,
["Request for '{}' failed: {}", uri, res.status()]
@ -561,7 +558,7 @@ impl ReqwestHttpSrc {
.and_then(|content_type| content_type.to_str().ok())
.and_then(|content_type| content_type.parse::<mime::Mime>().ok())
{
gst::debug!(CAT, obj: src, "Got content type {}", content_type);
gst::debug!(CAT, imp: self, "Got content type {}", content_type);
if let Some(ref mut caps) = caps {
let caps = caps.get_mut().unwrap();
let s = caps.structure_mut(0).unwrap();
@ -604,7 +601,7 @@ impl ReqwestHttpSrc {
}
}
gst::debug!(CAT, obj: src, "Request successful");
gst::debug!(CAT, imp: self, "Request successful");
Ok(State::Started {
uri,
@ -779,17 +776,11 @@ impl ObjectImpl for ReqwestHttpSrc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let res = match pspec.name() {
"location" => {
let location = value.get::<Option<&str>>().expect("type checked upstream");
self.set_location(obj, location)
self.set_location(location)
}
"user-agent" => {
let mut settings = self.settings.lock().unwrap();
@ -802,7 +793,7 @@ impl ObjectImpl for ReqwestHttpSrc {
}
"is-live" => {
let is_live = value.get().expect("type checked upstream");
obj.set_live(is_live);
self.instance().set_live(is_live);
Ok(())
}
"user-id" => {
@ -886,7 +877,7 @@ impl ObjectImpl for ReqwestHttpSrc {
if let Err(err) = res {
gst::error!(
CAT,
obj: obj,
imp: self,
"Failed to set property `{}`: {:?}",
pspec.name(),
err
@ -894,7 +885,7 @@ impl ObjectImpl for ReqwestHttpSrc {
}
}
fn property(&self, obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"location" => {
let settings = self.settings.lock().unwrap();
@ -906,7 +897,7 @@ impl ObjectImpl for ReqwestHttpSrc {
let settings = self.settings.lock().unwrap();
settings.user_agent.to_value()
}
"is-live" => obj.is_live().to_value(),
"is-live" => self.instance().is_live().to_value(),
"user-id" => {
let settings = self.settings.lock().unwrap();
settings.user_id.to_value()
@ -954,8 +945,10 @@ impl ObjectImpl for ReqwestHttpSrc {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.set_automatic_eos(false);
obj.set_format(gst::Format::Bytes);
}
@ -994,7 +987,7 @@ impl ElementImpl for ReqwestHttpSrc {
PAD_TEMPLATES.as_ref()
}
fn set_context(&self, element: &Self::Type, context: &gst::Context) {
fn set_context(&self, context: &gst::Context) {
if context.context_type() == REQWEST_CLIENT_CONTEXT {
let mut external_client = self.external_client.lock().unwrap();
let s = context.structure();
@ -1004,24 +997,23 @@ impl ElementImpl for ReqwestHttpSrc {
.unwrap_or(None);
}
self.parent_set_context(element, context);
self.parent_set_context(context);
}
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
if let gst::StateChange::ReadyToNull = transition {
*self.client.lock().unwrap() = None;
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}
impl BaseSrcImpl for ReqwestHttpSrc {
fn is_seekable(&self, _src: &Self::Type) -> bool {
fn is_seekable(&self) -> bool {
let state = self.state.lock().unwrap();
match *state {
State::Started { seekable, .. } => seekable,
@ -1029,7 +1021,7 @@ impl BaseSrcImpl for ReqwestHttpSrc {
}
}
fn size(&self, _src: &Self::Type) -> Option<u64> {
fn size(&self) -> Option<u64> {
let state = self.state.lock().unwrap();
match *state {
State::Started { size, .. } => size,
@ -1037,7 +1029,7 @@ impl BaseSrcImpl for ReqwestHttpSrc {
}
}
fn unlock(&self, _src: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn unlock(&self) -> Result<(), gst::ErrorMessage> {
let canceller = self.canceller.lock().unwrap();
if let Some(ref canceller) = *canceller {
canceller.abort();
@ -1045,7 +1037,7 @@ impl BaseSrcImpl for ReqwestHttpSrc {
Ok(())
}
fn start(&self, src: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
let mut state = self.state.lock().unwrap();
*state = State::Stopped;
@ -1061,9 +1053,9 @@ impl BaseSrcImpl for ReqwestHttpSrc {
})
.map(|uri| uri.clone())?;
gst::debug!(CAT, obj: src, "Starting for URI {}", uri);
gst::debug!(CAT, imp: self, "Starting for URI {}", uri);
*state = self.do_request(src, uri, 0, None).map_err(|err| {
*state = self.do_request(uri, 0, None).map_err(|err| {
err.unwrap_or_else(|| {
gst::error_msg!(gst::LibraryError::Failed, ["Interrupted during start"])
})
@ -1072,14 +1064,14 @@ impl BaseSrcImpl for ReqwestHttpSrc {
Ok(())
}
fn stop(&self, src: &Self::Type) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: src, "Stopping");
fn stop(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Stopping");
*self.state.lock().unwrap() = State::Stopped;
Ok(())
}
fn query(&self, element: &Self::Type, query: &mut gst::QueryRef) -> bool {
fn query(&self, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
match query.view_mut() {
@ -1093,11 +1085,11 @@ impl BaseSrcImpl for ReqwestHttpSrc {
q.add_scheduling_modes(&[gst::PadMode::Push]);
true
}
_ => BaseSrcImplExt::parent_query(self, element, query),
_ => BaseSrcImplExt::parent_query(self, query),
}
}
fn do_seek(&self, src: &Self::Type, segment: &mut gst::Segment) -> bool {
fn do_seek(&self, segment: &mut gst::Segment) -> bool {
let segment = segment.downcast_mut::<gst::format::Bytes>().unwrap();
let mut state = self.state.lock().unwrap();
@ -1110,7 +1102,7 @@ impl BaseSrcImpl for ReqwestHttpSrc {
..
} => (position, stop, uri.clone()),
State::Stopped => {
gst::element_error!(src, gst::LibraryError::Failed, ["Not started yet"]);
gst::element_imp_error!(self, gst::LibraryError::Failed, ["Not started yet"]);
return false;
}
@ -1119,21 +1111,21 @@ impl BaseSrcImpl for ReqwestHttpSrc {
let start = *segment.start().expect("No start position given");
let stop = segment.stop().map(|stop| *stop);
gst::debug!(CAT, obj: src, "Seeking to {}-{:?}", start, stop);
gst::debug!(CAT, imp: self, "Seeking to {}-{:?}", start, stop);
if position == start && old_stop == stop {
gst::debug!(CAT, obj: src, "No change to current request");
gst::debug!(CAT, imp: self, "No change to current request");
return true;
}
*state = State::Stopped;
match self.do_request(src, uri, start, stop) {
match self.do_request(uri, start, stop) {
Ok(s) => {
*state = s;
true
}
Err(Some(err)) => {
src.post_error_message(err);
self.post_error_message(err);
false
}
Err(None) => false,
@ -1144,7 +1136,6 @@ impl BaseSrcImpl for ReqwestHttpSrc {
impl PushSrcImpl for ReqwestHttpSrc {
fn create(
&self,
src: &Self::Type,
_buffer: Option<&mut gst::BufferRef>,
) -> Result<CreateSuccess, gst::FlowError> {
let mut state = self.state.lock().unwrap();
@ -1158,7 +1149,7 @@ impl PushSrcImpl for ReqwestHttpSrc {
..
} => (response, position, caps, tags),
State::Stopped => {
gst::element_error!(src, gst::LibraryError::Failed, ["Not started yet"]);
gst::element_imp_error!(self, gst::LibraryError::Failed, ["Not started yet"]);
return Err(gst::FlowError::Error);
}
@ -1169,8 +1160,8 @@ impl PushSrcImpl for ReqwestHttpSrc {
let mut current_response = match response.take() {
Some(response) => response,
None => {
gst::error!(CAT, obj: src, "Don't have a response");
gst::element_error!(src, gst::ResourceError::Read, ["Don't have a response"]);
gst::error!(CAT, imp: self, "Don't have a response");
gst::element_imp_error!(self, gst::ResourceError::Read, ["Don't have a response"]);
return Err(gst::FlowError::Error);
}
@ -1181,15 +1172,17 @@ impl PushSrcImpl for ReqwestHttpSrc {
drop(state);
if let Some(caps) = caps {
gst::debug!(CAT, obj: src, "Setting caps {:?}", caps);
src.set_caps(&caps)
gst::debug!(CAT, imp: self, "Setting caps {:?}", caps);
self.instance()
.set_caps(&caps)
.map_err(|_| gst::FlowError::NotNegotiated)?;
}
if let Some(tags) = tags {
gst::debug!(CAT, obj: src, "Sending iradio tags {:?}", tags);
let pad = src.static_pad("src").unwrap();
pad.push_event(gst::event::Tag::new(tags));
gst::debug!(CAT, imp: self, "Sending iradio tags {:?}", tags);
self.instance()
.src_pad()
.push_event(gst::event::Tag::new(tags));
}
let future = async {
@ -1205,12 +1198,12 @@ impl PushSrcImpl for ReqwestHttpSrc {
let res = match res {
Ok(res) => res,
Err(Some(err)) => {
gst::debug!(CAT, obj: src, "Error {:?}", err);
src.post_error_message(err);
gst::debug!(CAT, imp: self, "Error {:?}", err);
self.post_error_message(err);
return Err(gst::FlowError::Error);
}
Err(None) => {
gst::debug!(CAT, obj: src, "Flushing");
gst::debug!(CAT, imp: self, "Flushing");
return Err(gst::FlowError::Flushing);
}
};
@ -1223,7 +1216,7 @@ impl PushSrcImpl for ReqwestHttpSrc {
..
} => (response, position),
State::Stopped => {
gst::element_error!(src, gst::LibraryError::Failed, ["Not started yet"]);
gst::element_imp_error!(self, gst::LibraryError::Failed, ["Not started yet"]);
return Err(gst::FlowError::Error);
}
@ -1235,7 +1228,7 @@ impl PushSrcImpl for ReqwestHttpSrc {
gst::trace!(
CAT,
obj: src,
imp: self,
"Chunk of {} bytes received at offset {}",
chunk.len(),
offset
@ -1259,7 +1252,7 @@ impl PushSrcImpl for ReqwestHttpSrc {
}
None => {
/* No further data, end of stream */
gst::debug!(CAT, obj: src, "End of stream");
gst::debug!(CAT, imp: self, "End of stream");
*response = Some(current_response);
Err(gst::FlowError::Eos)
}
@ -1274,14 +1267,14 @@ impl URIHandlerImpl for ReqwestHttpSrc {
&["http", "https"]
}
fn uri(&self, _element: &Self::Type) -> Option<String> {
fn uri(&self) -> Option<String> {
let settings = self.settings.lock().unwrap();
settings.location.as_ref().map(Url::to_string)
}
fn set_uri(&self, element: &Self::Type, uri: &str) -> Result<(), glib::Error> {
self.set_location(element, Some(uri))
fn set_uri(&self, uri: &str) -> Result<(), glib::Error> {
self.set_location(Some(uri))
}
}

View file

@ -8,89 +8,85 @@
// SPDX-License-Identifier: MPL-2.0
macro_rules! err_flow {
($element:ident, read, $msg:literal) => {
($imp:ident, read, $msg:literal) => {
|err| {
gst::element_error!($element, gst::ResourceError::Read, [$msg, err]);
gst::element_imp_error!($imp, gst::ResourceError::Read, [$msg, err]);
gst::FlowError::Error
}
};
($element:ident, write, $msg:literal) => {
($imp:ident, write, $msg:literal) => {
|err| {
gst::element_error!($element, gst::ResourceError::Write, [$msg, err]);
gst::element_imp_error!($imp, gst::ResourceError::Write, [$msg, err]);
gst::FlowError::Error
}
};
($element:ident, buf_read) => {
err_flow!($element, read, "Failed to read buffer: {}")
($imp:ident, buf_read) => {
err_flow!($imp, read, "Failed to read buffer: {}")
};
($element:ident, aggr_header_write) => {
($imp:ident, aggr_header_write) => {
err_flow!(
$element,
$imp,
write,
"Failed to write aggregation header to the payload: {}"
)
};
($element:ident, leb_write) => {
($imp:ident, leb_write) => {
err_flow!(
$element,
$imp,
write,
"Failed to write leb128 size field to the payload: {}"
)
};
($element:ident, obu_write) => {
err_flow!(
$element,
write,
"Failed to write OBU bytes to the payload: {}"
)
($imp:ident, obu_write) => {
err_flow!($imp, write, "Failed to write OBU bytes to the payload: {}")
};
($element:ident, outbuf_alloc) => {
err_flow!($element, write, "Failed to allocate output buffer: {}")
($imp:ident, outbuf_alloc) => {
err_flow!($imp, write, "Failed to allocate output buffer: {}")
};
}
macro_rules! err_opt {
($element:ident, read, $msg:literal) => {
($imp:ident, read, $msg:literal) => {
|err| {
gst::element_error!($element, gst::ResourceError::Read, [$msg, err]);
gst::element_imp_error!($imp, gst::ResourceError::Read, [$msg, err]);
Option::<()>::None
}
};
($element:ident, write, $msg:literal) => {
($imp:ident, write, $msg:literal) => {
|err| {
gst::element_error!($element, gst::ResourceError::Write, [$msg, err]);
gst::element_imp_error!($imp, gst::ResourceError::Write, [$msg, err]);
Option::<()>::None
}
};
($element:ident, buf_alloc) => {
err_opt!($element, write, "Failed to allocate new buffer: {}")
($imp:ident, buf_alloc) => {
err_opt!($imp, write, "Failed to allocate new buffer: {}")
};
($element:ident, payload_buf) => {
err_opt!($element, read, "Failed to get RTP payload buffer: {}")
($imp:ident, payload_buf) => {
err_opt!($imp, read, "Failed to get RTP payload buffer: {}")
};
($element:ident, payload_map) => {
err_opt!($element, read, "Failed to map payload as readable: {}")
($imp:ident, payload_map) => {
err_opt!($imp, read, "Failed to map payload as readable: {}")
};
($element:ident, buf_take) => {
err_opt!($element, read, "Failed to take buffer from adapter: {}")
($imp:ident, buf_take) => {
err_opt!($imp, read, "Failed to take buffer from adapter: {}")
};
($element:ident, aggr_header_read) => {
err_opt!($element, read, "Failed to read aggregation header: {}")
($imp:ident, aggr_header_read) => {
err_opt!($imp, read, "Failed to read aggregation header: {}")
};
($element:ident, leb_read) => {
err_opt!($element, read, "Failed to read leb128 size field: {}")
($imp:ident, leb_read) => {
err_opt!($imp, read, "Failed to read leb128 size field: {}")
};
($element:ident, leb_write) => {
err_opt!($element, read, "Failed to write leb128 size field: {}")
($imp:ident, leb_write) => {
err_opt!($imp, read, "Failed to write leb128 size field: {}")
};
($element:ident, obu_read) => {
err_opt!($element, read, "Failed to read OBU header: {}")
($imp:ident, obu_read) => {
err_opt!($imp, read, "Failed to read OBU header: {}")
};
($element:ident, buf_read) => {
err_opt!($element, read, "Failed to read RTP buffer: {}")
($imp:ident, buf_read) => {
err_opt!($imp, read, "Failed to read RTP buffer: {}")
};
}

View file

@ -54,8 +54,8 @@ static TEMPORAL_DELIMITER: Lazy<gst::Memory> =
Lazy::new(|| gst::Memory::from_slice(&[0b0001_0010, 0]));
impl RTPAv1Depay {
fn reset(&self, element: &<Self as ObjectSubclass>::Type, state: &mut State) {
gst::debug!(CAT, obj: element, "resetting state");
fn reset(&self, state: &mut State) {
gst::debug!(CAT, imp: self, "resetting state");
*state = State::default()
}
@ -121,21 +121,20 @@ impl ElementImpl for RTPAv1Depay {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::debug!(CAT, obj: element, "changing state: {}", transition);
gst::debug!(CAT, imp: self, "changing state: {}", transition);
if matches!(transition, gst::StateChange::ReadyToPaused) {
let mut state = self.state.lock().unwrap();
self.reset(element, &mut state);
self.reset(&mut state);
}
let ret = self.parent_change_state(element, transition);
let ret = self.parent_change_state(transition);
if matches!(transition, gst::StateChange::PausedToReady) {
let mut state = self.state.lock().unwrap();
self.reset(element, &mut state);
self.reset(&mut state);
}
ret
@ -143,38 +142,37 @@ impl ElementImpl for RTPAv1Depay {
}
impl RTPBaseDepayloadImpl for RTPAv1Depay {
fn handle_event(&self, element: &Self::Type, event: gst::Event) -> bool {
fn handle_event(&self, event: gst::Event) -> bool {
match event.view() {
gst::EventView::Eos(_) | gst::EventView::FlushStop(_) => {
let mut state = self.state.lock().unwrap();
self.reset(element, &mut state);
self.reset(&mut state);
}
_ => (),
}
self.parent_handle_event(element, event)
self.parent_handle_event(event)
}
fn process_rtp_packet(
&self,
element: &Self::Type,
rtp: &gst_rtp::RTPBuffer<gst_rtp::rtp_buffer::Readable>,
) -> Option<gst::Buffer> {
gst::log!(
CAT,
obj: element,
imp: self,
"processing RTP packet with payload type {} and size {}",
rtp.payload_type(),
rtp.buffer().size(),
);
let payload = rtp.payload().map_err(err_opt!(element, payload_buf)).ok()?;
let payload = rtp.payload().map_err(err_opt!(self, payload_buf)).ok()?;
let mut state = self.state.lock().unwrap();
if rtp.buffer().flags().contains(gst::BufferFlags::DISCONT) {
gst::debug!(CAT, obj: element, "buffer discontinuity");
self.reset(element, &mut state);
gst::debug!(CAT, imp: self, "buffer discontinuity");
self.reset(&mut state);
}
// number of bytes that can be used in the next outgoing buffer
@ -186,7 +184,7 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
let mut byte = [0; 1];
reader
.read_exact(&mut byte)
.map_err(err_opt!(element, aggr_header_read))
.map_err(err_opt!(self, aggr_header_read))
.ok()?;
AggregationHeader::from(&byte)
};
@ -196,7 +194,7 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
if state.last_timestamp.is_some() && state.obu_fragment.is_some() {
gst::error!(
CAT,
obj: element,
imp: self,
concat!(
"invalid packet: packet is part of a new TU but ",
"the previous TU still has an incomplete OBU",
@ -205,7 +203,7 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
state.marked_packet,
state.last_timestamp
);
self.reset(element, &mut state);
self.reset(&mut state);
return None;
}
@ -230,20 +228,20 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
if !aggr_header.leading_fragment {
gst::error!(
CAT,
obj: element,
imp: self,
"invalid packet: ignores unclosed OBU fragment"
);
return None;
}
let (element_size, is_last_obu) =
find_element_info(element, rtp, &mut reader, &aggr_header, idx)?;
self.find_element_info(rtp, &mut reader, &aggr_header, idx)?;
let bytes_end = bytes.len();
bytes.resize(bytes_end + element_size as usize, 0);
reader
.read_exact(&mut bytes[bytes_end..])
.map_err(err_opt!(element, buf_read))
.map_err(err_opt!(self, buf_read))
.ok()?;
// if this OBU is complete, it can be appended to the adapter
@ -254,7 +252,7 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
obu.as_sized(size, leb_size)
};
let buffer = translate_obu(element, &mut Cursor::new(bytes.as_slice()), &full_obu)?;
let buffer = self.translate_obu(&mut Cursor::new(bytes.as_slice()), &full_obu)?;
state.adapter.push(buffer);
state.obu_fragment = None;
@ -264,24 +262,24 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
// handle other OBUs, including trailing fragments
while reader.position() < rtp.payload_size() as u64 {
let (element_size, is_last_obu) =
find_element_info(element, rtp, &mut reader, &aggr_header, idx)?;
self.find_element_info(rtp, &mut reader, &aggr_header, idx)?;
let header_pos = reader.position();
let mut bitreader = BitReader::endian(&mut reader, ENDIANNESS);
let obu = UnsizedObu::parse(&mut bitreader)
.map_err(err_opt!(element, obu_read))
.map_err(err_opt!(self, obu_read))
.ok()?;
reader
.seek(SeekFrom::Start(header_pos))
.map_err(err_opt!(element, buf_read))
.map_err(err_opt!(self, buf_read))
.ok()?;
// ignore these OBU types
if matches!(obu.obu_type, ObuType::TemporalDelimiter | ObuType::TileList) {
reader
.seek(SeekFrom::Current(element_size as i64))
.map_err(err_opt!(element, buf_read))
.map_err(err_opt!(self, buf_read))
.ok()?;
}
// trailing OBU fragments are stored in the state
@ -290,7 +288,7 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
let mut bytes = vec![0; bytes_left as usize];
reader
.read_exact(bytes.as_mut_slice())
.map_err(err_opt!(element, buf_read))
.map_err(err_opt!(self, buf_read))
.ok()?;
state.obu_fragment = Some((obu, bytes));
@ -303,7 +301,7 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
obu.as_sized(size, leb_size)
};
ready_obus.append(translate_obu(element, &mut reader, &full_obu)?);
ready_obus.append(self.translate_obu(&mut reader, &full_obu)?);
}
idx += 1;
@ -315,13 +313,13 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
if state.obu_fragment.is_some() {
gst::error!(
CAT,
obj: element,
imp: self,
concat!(
"invalid packet: has marker bit set, but ",
"last OBU is not yet complete"
)
);
self.reset(element, &mut state);
self.reset(&mut state);
return None;
}
@ -332,7 +330,7 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
if bytes_ready > 0 {
gst::log!(
CAT,
obj: element,
imp: self,
"creating buffer containing {} bytes of data...",
bytes_ready
);
@ -340,7 +338,7 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
state
.adapter
.take_buffer(bytes_ready)
.map_err(err_opt!(element, buf_take))
.map_err(err_opt!(self, buf_take))
.ok()?,
)
} else {
@ -349,100 +347,98 @@ impl RTPBaseDepayloadImpl for RTPAv1Depay {
}
}
/// Find out the next OBU element's size, and if it is the last OBU in the packet.
/// The reader is expected to be at the first byte of the element,
/// or its preceding size field if present,
/// and will be at the first byte past the element's size field afterwards.
fn find_element_info(
element: &<RTPAv1Depay as ObjectSubclass>::Type,
rtp: &gst_rtp::RTPBuffer<gst_rtp::rtp_buffer::Readable>,
reader: &mut Cursor<&[u8]>,
aggr_header: &AggregationHeader,
index: u32,
) -> Option<(u32, bool)> {
let element_size: u32;
let is_last_obu: bool;
impl RTPAv1Depay {
/// Find out the next OBU element's size, and if it is the last OBU in the packet.
/// The reader is expected to be at the first byte of the element,
/// or its preceding size field if present,
/// and will be at the first byte past the element's size field afterwards.
fn find_element_info(
&self,
rtp: &gst_rtp::RTPBuffer<gst_rtp::rtp_buffer::Readable>,
reader: &mut Cursor<&[u8]>,
aggr_header: &AggregationHeader,
index: u32,
) -> Option<(u32, bool)> {
let element_size: u32;
let is_last_obu: bool;
if let Some(count) = aggr_header.obu_count {
is_last_obu = index + 1 == count as u32;
element_size = if is_last_obu {
rtp.payload_size() - (reader.position() as u32)
} else {
let mut bitreader = BitReader::endian(reader, ENDIANNESS);
parse_leb128(&mut bitreader)
.map_err(err_opt!(element, leb_read))
.ok()? as u32
}
} else {
element_size = parse_leb128(&mut BitReader::endian(&mut *reader, ENDIANNESS))
.map_err(err_opt!(element, leb_read))
.ok()? as u32;
is_last_obu = match rtp
.payload_size()
.cmp(&(reader.position() as u32 + element_size))
{
Ordering::Greater => false,
Ordering::Equal => true,
Ordering::Less => {
gst::error!(
CAT,
obj: element,
"invalid packet: size field gives impossibly large OBU size"
);
return None;
if let Some(count) = aggr_header.obu_count {
is_last_obu = index + 1 == count as u32;
element_size = if is_last_obu {
rtp.payload_size() - (reader.position() as u32)
} else {
let mut bitreader = BitReader::endian(reader, ENDIANNESS);
parse_leb128(&mut bitreader)
.map_err(err_opt!(self, leb_read))
.ok()? as u32
}
};
} else {
element_size = parse_leb128(&mut BitReader::endian(&mut *reader, ENDIANNESS))
.map_err(err_opt!(self, leb_read))
.ok()? as u32;
is_last_obu = match rtp
.payload_size()
.cmp(&(reader.position() as u32 + element_size))
{
Ordering::Greater => false,
Ordering::Equal => true,
Ordering::Less => {
gst::error!(
CAT,
imp: self,
"invalid packet: size field gives impossibly large OBU size"
);
return None;
}
};
}
Some((element_size, is_last_obu))
}
Some((element_size, is_last_obu))
}
/// Using OBU data from an RTP packet, construct a buffer containing that OBU in AV1 bitstream format
fn translate_obu(&self, reader: &mut Cursor<&[u8]>, obu: &SizedObu) -> Option<gst::Buffer> {
let mut bytes = gst::Buffer::with_size(obu.full_size() as usize)
.map_err(err_opt!(self, buf_alloc))
.ok()?
.into_mapped_buffer_writable()
.unwrap();
/// Using OBU data from an RTP packet, construct a buffer containing that OBU in AV1 bitstream format
fn translate_obu(
element: &<RTPAv1Depay as ObjectSubclass>::Type,
reader: &mut Cursor<&[u8]>,
obu: &SizedObu,
) -> Option<gst::Buffer> {
let mut bytes = gst::Buffer::with_size(obu.full_size() as usize)
.map_err(err_opt!(element, buf_alloc))
.ok()?
.into_mapped_buffer_writable()
.unwrap();
// write OBU header
reader
.read_exact(&mut bytes[..obu.header_len as usize])
.map_err(err_opt!(element, buf_read))
.ok()?;
// set `has_size_field`
bytes[0] |= 1 << 1;
// skip internal size field if present
if obu.has_size_field {
parse_leb128(&mut BitReader::endian(&mut *reader, ENDIANNESS))
.map_err(err_opt!(element, leb_read))
// write OBU header
reader
.read_exact(&mut bytes[..obu.header_len as usize])
.map_err(err_opt!(self, buf_read))
.ok()?;
}
// write size field
write_leb128(
&mut BitWriter::endian(
Cursor::new(&mut bytes[obu.header_len as usize..]),
ENDIANNESS,
),
obu.size,
)
.map_err(err_opt!(element, leb_write))
.ok()?;
// set `has_size_field`
bytes[0] |= 1 << 1;
// write OBU payload
reader
.read_exact(&mut bytes[(obu.header_len + obu.leb_size) as usize..])
.map_err(err_opt!(element, buf_read))
// skip internal size field if present
if obu.has_size_field {
parse_leb128(&mut BitReader::endian(&mut *reader, ENDIANNESS))
.map_err(err_opt!(self, leb_read))
.ok()?;
}
// write size field
write_leb128(
&mut BitWriter::endian(
Cursor::new(&mut bytes[obu.header_len as usize..]),
ENDIANNESS,
),
obu.size,
)
.map_err(err_opt!(self, leb_write))
.ok()?;
Some(bytes.into_buffer())
// write OBU payload
reader
.read_exact(&mut bytes[(obu.header_len + obu.leb_size) as usize..])
.map_err(err_opt!(self, buf_read))
.ok()?;
Some(bytes.into_buffer())
}
}
#[cfg(test)]
@ -507,7 +503,7 @@ mod tests {
println!("running test {}...", idx);
let mut reader = Cursor::new(rtp_bytes.as_slice());
let actual = translate_obu(&element, &mut reader, &obu);
let actual = element.imp().translate_obu(&mut reader, &obu);
assert_eq!(reader.position(), rtp_bytes.len() as u64);
assert!(actual.is_some());
@ -568,7 +564,7 @@ mod tests {
println!("testing element {} with reader position {}...", obu_idx, reader.position());
let actual = find_element_info(&element, &rtp, &mut reader, &aggr_header, obu_idx as u32);
let actual = element.imp().find_element_info(&rtp, &mut reader, &aggr_header, obu_idx as u32);
assert_eq!(actual, Some(expected));
element_size = actual.unwrap().0;
}

View file

@ -95,8 +95,8 @@ impl Default for State {
}
impl RTPAv1Pay {
fn reset(&self, element: &<Self as ObjectSubclass>::Type, state: &mut State) {
gst::debug!(CAT, obj: element, "resetting state");
fn reset(&self, state: &mut State) {
gst::debug!(CAT, imp: self, "resetting state");
*state = State::default();
}
@ -105,7 +105,6 @@ impl RTPAv1Pay {
/// and constructs and sends new RTP packets when appropriate.
fn handle_new_obus(
&self,
element: &<Self as ObjectSubclass>::Type,
state: &mut State,
data: &[u8],
dts: Option<gst::ClockTime>,
@ -116,26 +115,26 @@ impl RTPAv1Pay {
while reader.position() < data.len() as u64 {
let obu_start = reader.position();
let obu = SizedObu::parse(&mut BitReader::endian(&mut reader, ENDIANNESS))
.map_err(err_flow!(element, buf_read))?;
.map_err(err_flow!(self, buf_read))?;
// tile lists and temporal delimiters should not be transmitted,
// see section 5 of the RTP AV1 spec
match obu.obu_type {
// completely ignore tile lists
ObuType::TileList => {
gst::log!(CAT, obj: element, "ignoring tile list OBU");
gst::log!(CAT, imp: self, "ignoring tile list OBU");
reader
.seek(SeekFrom::Current(
(obu.header_len + obu.leb_size + obu.size) as i64,
))
.map_err(err_flow!(element, buf_read))?;
.map_err(err_flow!(self, buf_read))?;
}
// keep these OBUs around for now so we know where temporal units end
ObuType::TemporalDelimiter => {
if obu.size != 0 {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["temporal delimiter OBUs should have empty payload"]
);
@ -156,21 +155,21 @@ impl RTPAv1Pay {
// read header
reader
.seek(SeekFrom::Start(obu_start))
.map_err(err_flow!(element, buf_read))?;
.map_err(err_flow!(self, buf_read))?;
reader
.read_exact(&mut bytes[0..(obu.header_len as usize)])
.map_err(err_flow!(element, buf_read))?;
.map_err(err_flow!(self, buf_read))?;
// skip size field
bytes[0] &= !2_u8; // set `has_size_field` to 0
reader
.seek(SeekFrom::Current(obu.leb_size as i64))
.map_err(err_flow!(element, buf_read))?;
.map_err(err_flow!(self, buf_read))?;
// read OBU bytes
reader
.read_exact(&mut bytes[(obu.header_len as usize)..bytes_total])
.map_err(err_flow!(element, buf_read))?;
.map_err(err_flow!(self, buf_read))?;
state.obus.push(ObuData {
info: obu,
@ -185,8 +184,8 @@ impl RTPAv1Pay {
let mut list = gst::BufferList::new();
{
let list = list.get_mut().unwrap();
while let Some(packet_data) = self.consider_new_packet(element, state, false) {
let buffer = self.generate_new_packet(element, state, packet_data)?;
while let Some(packet_data) = self.consider_new_packet(state, false) {
let buffer = self.generate_new_packet(state, packet_data)?;
list.add(buffer);
}
}
@ -200,15 +199,10 @@ impl RTPAv1Pay {
///
/// If `true` is passed for `force`, packets of any size will be accepted,
/// which is used in flushing the last OBUs after receiving an EOS for example.
fn consider_new_packet(
&self,
element: &<Self as ObjectSubclass>::Type,
state: &mut State,
force: bool,
) -> Option<PacketOBUData> {
fn consider_new_packet(&self, state: &mut State, force: bool) -> Option<PacketOBUData> {
gst::trace!(
CAT,
obj: element,
imp: self,
"{} new packet, currently storing {} OBUs",
if force { "forcing" } else { "considering" },
state.obus.len()
@ -216,7 +210,7 @@ impl RTPAv1Pay {
let mut data = state.temp_packet_data.take().unwrap_or_else(|| {
TempPacketData {
payload_limit: gst_rtp::RTPBuffer::calc_payload_len(element.mtu(), 0, 0),
payload_limit: gst_rtp::RTPBuffer::calc_payload_len(self.instance().mtu(), 0, 0),
packet: PacketOBUData {
payload_size: 1, // 1 byte is used for the aggregation header
omit_last_size_field: true,
@ -245,7 +239,7 @@ impl RTPAv1Pay {
// should this packet be finished here?
if current.obu_type == ObuType::TemporalDelimiter {
// remove the temporal delimiter, it is not supposed to be transmitted
gst::log!(CAT, obj: element, "ignoring temporal delimiter OBU");
gst::log!(CAT, imp: self, "ignoring temporal delimiter OBU");
state.obus.remove(packet.obu_count);
if packet.obu_count > 0 {
@ -332,13 +326,12 @@ impl RTPAv1Pay {
/// new RTP packet, filled with those OBUs.
fn generate_new_packet(
&self,
element: &<Self as ObjectSubclass>::Type,
state: &mut State,
packet: PacketOBUData,
) -> Result<gst::Buffer, gst::FlowError> {
gst::log!(
CAT,
obj: element,
imp: self,
"constructing new RTP packet with {} OBUs",
packet.obu_count
);
@ -346,8 +339,8 @@ impl RTPAv1Pay {
// prepare the outgoing buffer
let mut outbuf =
gst::Buffer::new_rtp_with_sizes(packet.payload_size, 0, 0).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Write,
["Failed to allocate output buffer: {}", err]
);
@ -389,7 +382,7 @@ impl RTPAv1Pay {
writer
.write(&aggr_header)
.map_err(err_flow!(element, aggr_header_write))?;
.map_err(err_flow!(self, aggr_header_write))?;
state.first_packet_in_seq = false;
}
@ -402,10 +395,10 @@ impl RTPAv1Pay {
&mut BitWriter::endian(&mut writer, ENDIANNESS),
obu.info.size + obu.info.header_len,
)
.map_err(err_flow!(element, leb_write))?;
.map_err(err_flow!(self, leb_write))?;
writer
.write(&obu.bytes)
.map_err(err_flow!(element, obu_write))?;
.map_err(err_flow!(self, obu_write))?;
state.obus.remove(0);
}
@ -423,14 +416,14 @@ impl RTPAv1Pay {
if !packet.omit_last_size_field {
write_leb128(&mut BitWriter::endian(&mut writer, ENDIANNESS), obu_size)
.map_err(err_flow!(element, leb_write))?;
.map_err(err_flow!(self, leb_write))?;
}
// if this OBU is not a fragment, handle it as usual
if packet.last_obu_fragment_size == None {
writer
.write(&state.obus[0].bytes)
.map_err(err_flow!(element, obu_write))?;
.map_err(err_flow!(self, obu_write))?;
state.obus.remove(0);
}
// otherwise write only a slice, and update the element
@ -438,7 +431,7 @@ impl RTPAv1Pay {
else {
writer
.write(&state.obus[0].bytes[0..obu_size as usize])
.map_err(err_flow!(element, obu_write))?;
.map_err(err_flow!(self, obu_write))?;
let new_size = state.obus[0].bytes.len() as u32 - obu_size;
state.obus[0] = ObuData {
@ -460,7 +453,7 @@ impl RTPAv1Pay {
gst::log!(
CAT,
obj: element,
imp: self,
"generated RTP packet of size {}",
outbuf.size()
);
@ -529,21 +522,20 @@ impl ElementImpl for RTPAv1Pay {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::debug!(CAT, obj: element, "changing state: {}", transition);
gst::debug!(CAT, imp: self, "changing state: {}", transition);
if matches!(transition, gst::StateChange::ReadyToPaused) {
let mut state = self.state.lock().unwrap();
self.reset(element, &mut state);
self.reset(&mut state);
}
let ret = self.parent_change_state(element, transition);
let ret = self.parent_change_state(transition);
if matches!(transition, gst::StateChange::PausedToReady) {
let mut state = self.state.lock().unwrap();
self.reset(element, &mut state);
self.reset(&mut state);
}
ret
@ -551,39 +543,31 @@ impl ElementImpl for RTPAv1Pay {
}
impl RTPBasePayloadImpl for RTPAv1Pay {
fn set_caps(&self, element: &Self::Type, _caps: &gst::Caps) -> Result<(), gst::LoggableError> {
element.set_options("video", true, "AV1", CLOCK_RATE);
fn set_caps(&self, _caps: &gst::Caps) -> Result<(), gst::LoggableError> {
self.instance()
.set_options("video", true, "AV1", CLOCK_RATE);
gst::debug!(CAT, obj: element, "setting caps");
gst::debug!(CAT, imp: self, "setting caps");
Ok(())
}
fn handle_buffer(
&self,
element: &Self::Type,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::trace!(
CAT,
obj: element,
"received buffer of size {}",
buffer.size()
);
fn handle_buffer(&self, buffer: gst::Buffer) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::trace!(CAT, imp: self, "received buffer of size {}", buffer.size());
let mut state = self.state.lock().unwrap();
if buffer.flags().contains(gst::BufferFlags::DISCONT) {
gst::debug!(CAT, obj: element, "buffer discontinuity");
self.reset(element, &mut state);
gst::debug!(CAT, imp: self, "buffer discontinuity");
self.reset(&mut state);
}
let dts = buffer.dts();
let pts = buffer.pts();
let buffer = buffer.into_mapped_buffer_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to map buffer readable"]
);
@ -591,18 +575,18 @@ impl RTPBasePayloadImpl for RTPAv1Pay {
gst::FlowError::Error
})?;
let list = self.handle_new_obus(element, &mut state, buffer.as_slice(), dts, pts)?;
let list = self.handle_new_obus(&mut state, buffer.as_slice(), dts, pts)?;
drop(state);
if !list.is_empty() {
element.push_list(list)
self.instance().push_list(list)
} else {
Ok(gst::FlowSuccess::Ok)
}
}
fn sink_event(&self, element: &Self::Type, event: gst::Event) -> bool {
gst::log!(CAT, obj: element, "sink event: {}", event.type_());
fn sink_event(&self, event: gst::Event) -> bool {
gst::log!(CAT, imp: self, "sink event: {}", event.type_());
match event.view() {
gst::EventView::Eos(_) => {
@ -612,29 +596,27 @@ impl RTPBasePayloadImpl for RTPAv1Pay {
let mut state = self.state.lock().unwrap();
let list = list.get_mut().unwrap();
while let Some(packet_data) =
self.consider_new_packet(element, &mut state, true)
{
match self.generate_new_packet(element, &mut state, packet_data) {
while let Some(packet_data) = self.consider_new_packet(&mut state, true) {
match self.generate_new_packet(&mut state, packet_data) {
Ok(buffer) => list.add(buffer),
Err(_) => break,
}
}
self.reset(element, &mut state);
self.reset(&mut state);
}
if !list.is_empty() {
let _ = element.push_list(list);
let _ = self.instance().push_list(list);
}
}
gst::EventView::FlushStop(_) => {
let mut state = self.state.lock().unwrap();
self.reset(element, &mut state);
self.reset(&mut state);
}
_ => (),
}
self.parent_sink_event(element, event)
self.parent_sink_event(event)
}
}
@ -824,7 +806,7 @@ mod tests {
*state = input_data[idx].1.clone();
assert_eq!(
pay.consider_new_packet(&element, &mut state, input_data[idx].0),
pay.consider_new_packet(&mut state, input_data[idx].0),
results[idx].0,
);
assert_eq!(state.obus, results[idx].1.obus);

View file

@ -127,7 +127,6 @@ impl ElementImpl for WhipSink {
fn request_new_pad(
&self,
element: &Self::Type,
templ: &gst::PadTemplate,
name: Option<String>,
caps: Option<&gst::Caps>,
@ -136,17 +135,16 @@ impl ElementImpl for WhipSink {
let sink_pad = gst::GhostPad::new(Some(&wb_sink_pad.name()), gst::PadDirection::Sink);
sink_pad.set_target(Some(&wb_sink_pad)).unwrap();
element.add_pad(&sink_pad).unwrap();
self.instance().add_pad(&sink_pad).unwrap();
Some(sink_pad.upcast())
}
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
let ret = self.parent_change_state(element, transition);
let ret = self.parent_change_state(transition);
if transition == gst::StateChange::PausedToReady {
// Interrupt requests in progress, if any
if let Some(canceller) = &*self.canceller.lock().unwrap() {
@ -193,13 +191,7 @@ impl ObjectImpl for WhipSink {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"whip-endpoint" => {
let mut settings = self.settings.lock().unwrap();
@ -219,7 +211,7 @@ impl ObjectImpl for WhipSink {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"whip-endpoint" => {
let settings = self.settings.lock().unwrap();
@ -237,8 +229,10 @@ impl ObjectImpl for WhipSink {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.set_suppressed_flags(gst::ElementFlags::SINK | gst::ElementFlags::SOURCE);
obj.set_element_flags(gst::ElementFlags::SINK);
obj.add(&self.webrtcbin).unwrap();

View file

@ -77,14 +77,14 @@ impl ObjectSubclass for TextAhead {
TextAhead::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|imp, element| imp.sink_chain(pad, element, buffer),
|imp| imp.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
TextAhead::catch_panic_pad_function(
parent,
|| false,
|imp, element| imp.sink_event(pad, element, event),
|imp| imp.sink_event(pad, event),
)
})
.build();
@ -144,13 +144,7 @@ impl ObjectImpl for TextAhead {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
@ -173,7 +167,7 @@ impl ObjectImpl for TextAhead {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
@ -186,9 +180,10 @@ impl ObjectImpl for TextAhead {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sink_pad).unwrap();
obj.add_pad(&self.src_pad).unwrap();
}
@ -242,10 +237,9 @@ impl ElementImpl for TextAhead {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
let res = self.parent_change_state(element, transition);
let res = self.parent_change_state(transition);
match transition {
gst::StateChange::ReadyToPaused => *self.state.lock().unwrap() = State::default(),
@ -264,7 +258,6 @@ impl TextAhead {
fn sink_chain(
&self,
_pad: &gst::Pad,
element: &super::TextAhead,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let pts = buffer.pts();
@ -279,7 +272,7 @@ impl TextAhead {
// queue buffer
let mut state = self.state.lock().unwrap();
gst::log!(CAT, obj: element, "input {:?}: {}", pts, text);
gst::log!(CAT, imp: self, "input {:?}: {}", pts, text);
state.pending.push(Input {
text,
@ -295,26 +288,27 @@ impl TextAhead {
// then check if we can output
// FIXME: this won't work on live pipelines as we can't really report latency
if state.pending.len() > n_ahead {
self.push_pending(element, &mut state)
self.push_pending(&mut state)
} else {
Ok(gst::FlowSuccess::Ok)
}
}
fn sink_event(&self, pad: &gst::Pad, element: &super::TextAhead, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
match event.view() {
gst::EventView::Eos(_) => {
let mut state = self.state.lock().unwrap();
gst::debug!(CAT, obj: element, "eos");
gst::debug!(CAT, imp: self, "eos");
while !state.pending.is_empty() {
let _ = self.push_pending(element, &mut state);
let _ = self.push_pending(&mut state);
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
gst::EventView::Caps(_caps) => {
// set caps on src pad
let element = self.instance();
let templ = element.class().pad_template("src").unwrap();
let _ = self.src_pad.push_event(gst::event::Caps::new(templ.caps()));
true
@ -332,16 +326,15 @@ impl TextAhead {
}
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
/// push first pending buffer as current and all the other ones as ahead text
fn push_pending(
&self,
element: &super::TextAhead,
state: &mut MutexGuard<State>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
if state.done {
@ -390,7 +383,7 @@ impl TextAhead {
}
}
gst::log!(CAT, obj: element, "output {:?}: {}", pts, text);
gst::log!(CAT, imp: self, "output {:?}: {}", pts, text);
let mut output = gst::Buffer::from_mut_slice(text.into_bytes());
{

View file

@ -52,7 +52,6 @@ impl JsonGstEnc {
fn sink_chain(
&self,
_pad: &gst::Pad,
element: &super::JsonGstEnc,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let pts = buffer.pts();
@ -66,8 +65,8 @@ impl JsonGstEnc {
};
let mut json = serde_json::to_string(&line).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Write,
["Failed to serialize as json {}", err]
);
@ -92,8 +91,8 @@ impl JsonGstEnc {
}
let map = buffer.map_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to map buffer readable"]
);
@ -102,8 +101,8 @@ impl JsonGstEnc {
})?;
let text = std::str::from_utf8(map.as_slice()).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to map decode as utf8: {}", err]
);
@ -112,8 +111,8 @@ impl JsonGstEnc {
})?;
let data: &serde_json::value::RawValue = serde_json::from_str(text).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to parse input as json: {}", err]
);
@ -128,8 +127,8 @@ impl JsonGstEnc {
};
let mut json = serde_json::to_string(&line).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Write,
["Failed to serialize as json {}", err]
);
@ -149,7 +148,7 @@ impl JsonGstEnc {
self.srcpad.push(buf)
}
fn sink_event(&self, pad: &gst::Pad, element: &super::JsonGstEnc, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -170,8 +169,8 @@ impl JsonGstEnc {
let caps = gst::Caps::builder("application/x-json").build();
self.srcpad.push_event(gst::event::Caps::new(&caps))
}
EventView::Eos(_) => pad.event_default(Some(element), event),
_ => pad.event_default(Some(element), event),
EventView::Eos(_) => pad.event_default(Some(&*self.instance()), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
}
@ -189,14 +188,14 @@ impl ObjectSubclass for JsonGstEnc {
JsonGstEnc::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|enc, element| enc.sink_chain(pad, element, buffer),
|enc| enc.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
JsonGstEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.sink_event(pad, element, event),
|enc| enc.sink_event(pad, event),
)
})
.build();
@ -213,9 +212,10 @@ impl ObjectSubclass for JsonGstEnc {
}
impl ObjectImpl for JsonGstEnc {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -266,10 +266,9 @@ impl ElementImpl for JsonGstEnc {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused | gst::StateChange::PausedToReady => {
@ -280,6 +279,6 @@ impl ElementImpl for JsonGstEnc {
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -36,10 +36,12 @@ struct PullState {
}
impl PullState {
fn new(element: &super::JsonGstParse, pad: &gst::Pad) -> Self {
fn new(imp: &JsonGstParse, pad: &gst::Pad) -> Self {
Self {
need_stream_start: true,
stream_id: pad.create_stream_id(element, Some("src")).to_string(),
stream_id: pad
.create_stream_id(&*imp.instance(), Some("src"))
.to_string(),
offset: 0,
duration: None,
}
@ -124,7 +126,7 @@ impl State {
Ok(Some(line))
}
fn create_events(&mut self, element: &super::JsonGstParse) -> Vec<gst::Event> {
fn create_events(&mut self, imp: &JsonGstParse) -> Vec<gst::Event> {
let mut events = Vec::new();
if self.need_flush_stop {
@ -155,7 +157,7 @@ impl State {
let caps = caps_builder.build();
events.push(gst::event::Caps::new(&caps));
gst::info!(CAT, obj: element, "Caps changed to {:?}", &caps);
gst::info!(CAT, imp: imp, "Caps changed to {:?}", &caps);
self.need_caps = false;
}
@ -176,7 +178,6 @@ impl State {
fn add_buffer_metadata(
&mut self,
_element: &super::JsonGstParse,
buffer: &mut gst::buffer::Buffer,
pts: Option<gst::ClockTime>,
duration: Option<gst::ClockTime>,
@ -205,15 +206,14 @@ pub struct JsonGstParse {
impl JsonGstParse {
fn handle_buffer(
&self,
element: &super::JsonGstParse,
buffer: Option<gst::Buffer>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state = self.state.lock().unwrap();
let drain = if let Some(buffer) = buffer {
let buffer = buffer.into_mapped_buffer_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to map buffer readable"]
);
@ -238,7 +238,7 @@ impl JsonGstParse {
})) => {
gst::debug!(
CAT,
obj: element,
imp: self,
"Got buffer with timestamp {} and duration {}",
pts.display(),
duration.display(),
@ -246,7 +246,7 @@ impl JsonGstParse {
if !seeking {
let data = data.to_string();
let mut events = state.create_events(element);
let mut events = state.create_events(self);
let mut buffer = gst::Buffer::from_mut_slice(data.into_bytes());
@ -260,7 +260,7 @@ impl JsonGstParse {
}
}
state.add_buffer_metadata(element, &mut buffer, pts, duration);
state.add_buffer_metadata(&mut buffer, pts, duration);
let send_eos = buffer
.pts()
@ -272,13 +272,13 @@ impl JsonGstParse {
drop(state);
for event in events {
gst::debug!(CAT, obj: element, "Pushing event {:?}", event);
gst::debug!(CAT, imp: self, "Pushing event {:?}", event);
self.srcpad.push_event(event);
}
self.srcpad.push(buffer).map_err(|err| {
if err != gst::FlowError::Flushing {
gst::error!(CAT, obj: element, "Pushing buffer returned {:?}", err);
gst::error!(CAT, imp: self, "Pushing buffer returned {:?}", err);
}
err
})?;
@ -289,27 +289,27 @@ impl JsonGstParse {
state = self.state.lock().unwrap();
} else {
state = self.handle_skipped_line(element, pts, state);
state = self.handle_skipped_line(pts, state);
}
}
Ok(Some(Line::Header { format })) => {
if state.format.is_none() {
state.format = Some(format);
} else {
gst::warning!(CAT, obj: element, "Ignoring format change",);
gst::warning!(CAT, imp: self, "Ignoring format change",);
}
}
Err((line, err)) => {
gst::error!(
CAT,
obj: element,
imp: self,
"Couldn't parse line '{:?}': {:?}",
std::str::from_utf8(line),
err
);
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Couldn't parse line '{:?}': {:?}", line, err]
);
@ -318,7 +318,7 @@ impl JsonGstParse {
}
Ok(None) => {
if drain && state.pull.is_some() {
eprintln!("Finished draining");
gst::debug!(CAT, imp: self, "Finished draining");
break Err(gst::FlowError::Eos);
}
break Ok(gst::FlowSuccess::Ok);
@ -329,7 +329,6 @@ impl JsonGstParse {
fn handle_skipped_line(
&self,
element: &super::JsonGstParse,
pts: impl Into<Option<gst::ClockTime>>,
mut state: MutexGuard<State>,
) -> MutexGuard<State> {
@ -339,7 +338,7 @@ impl JsonGstParse {
state.replay_last_line = true;
state.need_flush_stop = true;
gst::debug!(CAT, obj: element, "Done seeking");
gst::debug!(CAT, imp: self, "Done seeking");
}
drop(state);
@ -347,11 +346,7 @@ impl JsonGstParse {
self.state.lock().unwrap()
}
fn sink_activate(
&self,
pad: &gst::Pad,
element: &super::JsonGstParse,
) -> Result<(), gst::LoggableError> {
fn sink_activate(&self, pad: &gst::Pad) -> Result<(), gst::LoggableError> {
let mode = {
let mut query = gst::query::Scheduling::new();
let mut state = self.state.lock().unwrap();
@ -366,7 +361,7 @@ impl JsonGstParse {
{
gst::debug!(CAT, obj: pad, "Activating in Pull mode");
state.pull = Some(PullState::new(element, &self.srcpad));
state.pull = Some(PullState::new(self, &self.srcpad));
gst::PadMode::Pull
} else {
@ -379,22 +374,10 @@ impl JsonGstParse {
Ok(())
}
fn start_task(&self, element: &super::JsonGstParse) -> Result<(), gst::LoggableError> {
let element_weak = element.downgrade();
let pad_weak = self.sinkpad.downgrade();
fn start_task(&self) -> Result<(), gst::LoggableError> {
let self_ = self.ref_counted();
let res = self.sinkpad.start_task(move || {
let element = match element_weak.upgrade() {
Some(element) => element,
None => {
if let Some(pad) = pad_weak.upgrade() {
pad.pause_task().unwrap();
}
return;
}
};
let parse = element.imp();
parse.loop_fn(&element);
self_.loop_fn();
});
if res.is_err() {
return Err(gst::loggable_error!(CAT, "Failed to start pad task"));
@ -405,13 +388,12 @@ impl JsonGstParse {
fn sink_activatemode(
&self,
_pad: &gst::Pad,
element: &super::JsonGstParse,
mode: gst::PadMode,
active: bool,
) -> Result<(), gst::LoggableError> {
if mode == gst::PadMode::Pull {
if active {
self.start_task(element)?;
self.start_task()?;
} else {
let _ = self.sinkpad.stop_task();
}
@ -420,11 +402,8 @@ impl JsonGstParse {
Ok(())
}
fn scan_duration(
&self,
element: &super::JsonGstParse,
) -> Result<Option<gst::ClockTime>, gst::LoggableError> {
gst::debug!(CAT, obj: element, "Scanning duration");
fn scan_duration(&self) -> Result<Option<gst::ClockTime>, gst::LoggableError> {
gst::debug!(CAT, imp: self, "Scanning duration");
/* First let's query the bytes duration upstream */
let mut q = gst::query::Duration::new(gst::Format::Bytes);
@ -493,7 +472,7 @@ impl JsonGstParse {
if last_pts.is_some() || offset == 0 {
gst::debug!(
CAT,
obj: element,
imp: self,
"Duration scan done, last_pts: {:?}",
last_pts
);
@ -502,14 +481,14 @@ impl JsonGstParse {
}
}
fn push_eos(&self, element: &super::JsonGstParse) {
fn push_eos(&self) {
let mut state = self.state.lock().unwrap();
if state.seeking {
state.need_flush_stop = true;
}
let mut events = state.create_events(element);
let mut events = state.create_events(self);
let mut eos_event = gst::event::Eos::builder();
if let Some(seek_seqnum) = state.seek_seqnum {
@ -522,12 +501,12 @@ impl JsonGstParse {
drop(state);
for event in events {
gst::debug!(CAT, obj: element, "Pushing event {:?}", event);
gst::debug!(CAT, imp: self, "Pushing event {:?}", event);
self.srcpad.push_event(event);
}
}
fn loop_fn(&self, element: &super::JsonGstParse) {
fn loop_fn(&self) {
let mut state = self.state.lock().unwrap();
let State { ref mut pull, .. } = *state;
let mut pull = pull.as_mut().unwrap();
@ -539,7 +518,7 @@ impl JsonGstParse {
drop(state);
if scan_duration {
match self.scan_duration(element) {
match self.scan_duration() {
Ok(pts) => {
let mut state = self.state.lock().unwrap();
let mut pull = state.pull.as_mut().unwrap();
@ -548,8 +527,8 @@ impl JsonGstParse {
Err(err) => {
err.log();
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Failed to scan duration"]
);
@ -571,8 +550,8 @@ impl JsonGstParse {
Err(flow) => {
gst::error!(CAT, obj: &self.sinkpad, "Failed to pull, reason: {:?}", flow);
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Failed,
["Streaming stopped, failed to pull buffer"]
);
@ -582,23 +561,23 @@ impl JsonGstParse {
}
};
if let Err(flow) = self.handle_buffer(element, buffer) {
if let Err(flow) = self.handle_buffer(buffer) {
match flow {
gst::FlowError::Flushing => {
gst::debug!(CAT, obj: element, "Pausing after flow {:?}", flow);
gst::debug!(CAT, imp: self, "Pausing after flow {:?}", flow);
}
gst::FlowError::Eos => {
self.push_eos(element);
self.push_eos();
gst::debug!(CAT, obj: element, "Pausing after flow {:?}", flow);
gst::debug!(CAT, imp: self, "Pausing after flow {:?}", flow);
}
_ => {
self.push_eos(element);
self.push_eos();
gst::error!(CAT, obj: element, "Pausing after flow {:?}", flow);
gst::error!(CAT, imp: self, "Pausing after flow {:?}", flow);
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Failed,
["Streaming stopped, reason: {:?}", flow]
);
@ -612,12 +591,11 @@ impl JsonGstParse {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::JsonGstParse,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
self.handle_buffer(element, Some(buffer))
self.handle_buffer(Some(buffer))
}
fn flush(&self, mut state: &mut State) {
@ -634,7 +612,7 @@ impl JsonGstParse {
state.format = None;
}
fn sink_event(&self, pad: &gst::Pad, element: &super::JsonGstParse, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -655,14 +633,14 @@ impl JsonGstParse {
self.flush(&mut state);
drop(state);
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::Eos(_) => {
gst::log!(CAT, obj: pad, "Draining");
if let Err(err) = self.handle_buffer(element, None) {
if let Err(err) = self.handle_buffer(None) {
gst::error!(CAT, obj: pad, "Failed to drain parser: {:?}", err);
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => {
if event.is_sticky()
@ -674,15 +652,15 @@ impl JsonGstParse {
state.pending_events.push(event);
true
} else {
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
}
}
}
fn perform_seek(&self, event: &gst::event::Seek, element: &super::JsonGstParse) -> bool {
fn perform_seek(&self, event: &gst::event::Seek) -> bool {
if self.state.lock().unwrap().pull.is_none() {
gst::error!(CAT, obj: element, "seeking is only supported in pull mode");
gst::error!(CAT, imp: self, "seeking is only supported in pull mode");
return false;
}
@ -691,7 +669,7 @@ impl JsonGstParse {
let mut start: Option<gst::ClockTime> = match start.try_into() {
Ok(start) => start,
Err(_) => {
gst::error!(CAT, obj: element, "seek has invalid format");
gst::error!(CAT, imp: self, "seek has invalid format");
return false;
}
};
@ -699,18 +677,18 @@ impl JsonGstParse {
let mut stop: Option<gst::ClockTime> = match stop.try_into() {
Ok(stop) => stop,
Err(_) => {
gst::error!(CAT, obj: element, "seek has invalid format");
gst::error!(CAT, imp: self, "seek has invalid format");
return false;
}
};
if !flags.contains(gst::SeekFlags::FLUSH) {
gst::error!(CAT, obj: element, "only flushing seeks are supported");
gst::error!(CAT, imp: self, "only flushing seeks are supported");
return false;
}
if start_type == gst::SeekType::End || stop_type == gst::SeekType::End {
gst::error!(CAT, obj: element, "Relative seeks are not supported");
gst::error!(CAT, imp: self, "Relative seeks are not supported");
return false;
}
@ -720,14 +698,14 @@ impl JsonGstParse {
.seqnum(seek_seqnum)
.build();
gst::debug!(CAT, obj: element, "Sending event {:?} upstream", event);
gst::debug!(CAT, imp: self, "Sending event {:?} upstream", event);
self.sinkpad.push_event(event);
let event = gst::event::FlushStart::builder()
.seqnum(seek_seqnum)
.build();
gst::debug!(CAT, obj: element, "Pushing event {:?}", event);
gst::debug!(CAT, imp: self, "Pushing event {:?}", event);
self.srcpad.push_event(event);
self.sinkpad.pause_task().unwrap();
@ -755,7 +733,7 @@ impl JsonGstParse {
/* Drop our state while we push a serialized event upstream */
drop(state);
gst::debug!(CAT, obj: element, "Sending event {:?} upstream", event);
gst::debug!(CAT, imp: self, "Sending event {:?} upstream", event);
self.sinkpad.push_event(event);
state = self.state.lock().unwrap();
@ -764,7 +742,7 @@ impl JsonGstParse {
.segment
.do_seek(rate, flags, start_type, start, stop_type, stop);
match self.start_task(element) {
match self.start_task() {
Err(error) => {
error.log();
false
@ -773,22 +751,17 @@ impl JsonGstParse {
}
}
fn src_event(&self, pad: &gst::Pad, element: &super::JsonGstParse, event: gst::Event) -> bool {
fn src_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() {
EventView::Seek(e) => self.perform_seek(e, element),
_ => pad.event_default(Some(element), event),
EventView::Seek(e) => self.perform_seek(e),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::JsonGstParse,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
@ -838,7 +811,7 @@ impl JsonGstParse {
self.sinkpad.peer_query(query)
}
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
}
@ -856,7 +829,7 @@ impl ObjectSubclass for JsonGstParse {
JsonGstParse::catch_panic_pad_function(
parent,
|| Err(gst::loggable_error!(CAT, "Panic activating sink pad")),
|parse, element| parse.sink_activate(pad, element),
|parse| parse.sink_activate(pad),
)
})
.activatemode_function(|pad, parent, mode, active| {
@ -868,21 +841,21 @@ impl ObjectSubclass for JsonGstParse {
"Panic activating sink pad with mode"
))
},
|parse, element| parse.sink_activatemode(pad, element, mode, active),
|parse| parse.sink_activatemode(pad, mode, active),
)
})
.chain_function(|pad, parent, buffer| {
JsonGstParse::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|parse, element| parse.sink_chain(pad, element, buffer),
|parse| parse.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
JsonGstParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.sink_event(pad, element, event),
|parse| parse.sink_event(pad, event),
)
})
.build();
@ -893,14 +866,14 @@ impl ObjectSubclass for JsonGstParse {
JsonGstParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_event(pad, element, event),
|parse| parse.src_event(pad, event),
)
})
.query_function(|pad, parent, query| {
JsonGstParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_query(pad, element, query),
|parse| parse.src_query(pad, query),
)
})
.build();
@ -914,9 +887,10 @@ impl ObjectSubclass for JsonGstParse {
}
impl ObjectImpl for JsonGstParse {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -966,10 +940,9 @@ impl ElementImpl for JsonGstParse {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused | gst::StateChange::PausedToReady => {
@ -980,6 +953,6 @@ impl ElementImpl for JsonGstParse {
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -49,20 +49,19 @@ impl RegEx {
fn sink_chain(
&self,
_pad: &gst::Pad,
element: &super::RegEx,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let data = buffer.map_readable().map_err(|_| {
gst::error!(CAT, obj: element, "Can't map buffer readable");
gst::element_error!(element, gst::CoreError::Failed, ["Failed to map buffer"]);
gst::error!(CAT, imp: self, "Can't map buffer readable");
gst::element_imp_error!(self, gst::CoreError::Failed, ["Failed to map buffer"]);
gst::FlowError::Error
})?;
let mut data = std::str::from_utf8(&data)
.map_err(|err| {
gst::error!(CAT, obj: element, "Can't decode utf8: {}", err);
gst::element_error!(
element,
gst::error!(CAT, imp: self, "Can't decode utf8: {}", err);
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Failed to decode utf8: {}", err]
);
@ -117,7 +116,7 @@ impl ObjectSubclass for RegEx {
RegEx::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|regex, element| regex.sink_chain(pad, element, buffer),
|regex| regex.sink_chain(pad, buffer),
)
})
.flags(gst::PadFlags::PROXY_CAPS | gst::PadFlags::FIXED_CAPS)
@ -157,20 +156,15 @@ impl ObjectImpl for RegEx {
PROPERTIES.as_ref()
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"commands" => {
let mut state = self.state.lock().unwrap();
@ -191,7 +185,11 @@ impl ObjectImpl for RegEx {
let pattern = match s.get::<Option<String>>("pattern") {
Ok(Some(pattern)) => pattern,
Ok(None) | Err(_) => {
gst::error!(CAT, "All commands require a pattern field as a string");
gst::error!(
CAT,
imp: self,
"All commands require a pattern field as a string"
);
continue;
}
};
@ -199,7 +197,7 @@ impl ObjectImpl for RegEx {
let regex = match Regex::new(&pattern) {
Ok(regex) => regex,
Err(err) => {
gst::error!(CAT, "Failed to compile regex: {:?}", err);
gst::error!(CAT, imp: self, "Failed to compile regex: {:?}", err);
continue;
}
};
@ -211,6 +209,7 @@ impl ObjectImpl for RegEx {
Ok(None) | Err(_) => {
gst::error!(
CAT,
imp: self,
"Replace operations require a replacement field as a string"
);
continue;
@ -223,7 +222,7 @@ impl ObjectImpl for RegEx {
});
}
val => {
gst::error!(CAT, "Unknown operation {}", val);
gst::error!(CAT, imp: self, "Unknown operation {}", val);
}
}
}
@ -232,7 +231,7 @@ impl ObjectImpl for RegEx {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"commands" => {
let state = self.state.lock().unwrap();

View file

@ -84,7 +84,7 @@ fn is_punctuation(word: &str) -> bool {
}
impl TextWrap {
fn update_wrapper(&self, element: &super::TextWrap) {
fn update_wrapper(&self) {
let settings = self.settings.lock().unwrap();
let mut state = self.state.lock().unwrap();
@ -97,7 +97,7 @@ impl TextWrap {
if let Some(dictionary) = &settings.dictionary {
let dict_file = match File::open(dictionary) {
Err(err) => {
gst::error!(CAT, obj: element, "Failed to open dictionary file: {}", err);
gst::error!(CAT, imp: self, "Failed to open dictionary file: {}", err);
return;
}
Ok(dict_file) => dict_file,
@ -106,12 +106,7 @@ impl TextWrap {
let mut reader = io::BufReader::new(dict_file);
let standard = match Standard::any_from_reader(&mut reader) {
Err(err) => {
gst::error!(
CAT,
obj: element,
"Failed to load standard from file: {}",
err
);
gst::error!(CAT, imp: self, "Failed to load standard from file: {}", err);
return;
}
Ok(standard) => standard,
@ -128,28 +123,27 @@ impl TextWrap {
fn sink_chain(
&self,
_pad: &gst::Pad,
element: &super::TextWrap,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
self.update_wrapper(element);
self.update_wrapper();
let mut pts = buffer.pts().ok_or_else(|| {
gst::error!(CAT, obj: element, "Need timestamped buffers");
gst::error!(CAT, imp: self, "Need timestamped buffers");
gst::FlowError::Error
})?;
let duration = buffer.duration().ok_or_else(|| {
gst::error!(CAT, obj: element, "Need buffers with duration");
gst::error!(CAT, imp: self, "Need buffers with duration");
gst::FlowError::Error
})?;
let data = buffer.map_readable().map_err(|_| {
gst::error!(CAT, obj: element, "Can't map buffer readable");
gst::error!(CAT, imp: self, "Can't map buffer readable");
gst::FlowError::Error
})?;
let data = std::str::from_utf8(&data).map_err(|err| {
gst::error!(CAT, obj: element, "Can't decode utf8: {}", err);
gst::error!(CAT, imp: self, "Can't decode utf8: {}", err);
gst::FlowError::Error
})?;
@ -225,7 +219,7 @@ impl TextWrap {
.join("\n");
gst::info!(
CAT,
obj: element,
imp: self,
"Outputting contents {}, ts: {}, duration: {}",
contents.to_string(),
state.start_ts.display(),
@ -318,7 +312,7 @@ impl TextWrap {
}
}
fn sink_event(&self, pad: &gst::Pad, element: &super::TextWrap, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
use gst::EventView;
@ -330,7 +324,7 @@ impl TextWrap {
if state.start_ts.is_some() {
true
} else {
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
}
EventView::FlushStart(_) => {
@ -339,7 +333,7 @@ impl TextWrap {
*state = State::default();
state.options = options;
drop(state);
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::Eos(_) => {
let mut state = self.state.lock().unwrap();
@ -363,18 +357,13 @@ impl TextWrap {
} else {
drop(state);
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::TextWrap,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
@ -390,7 +379,7 @@ impl TextWrap {
let our_latency: gst::ClockTime = self.settings.lock().unwrap().accumulate_time;
gst::info!(
CAT,
obj: element,
imp: self,
"Reporting our latency {} + {}",
our_latency,
min
@ -399,7 +388,7 @@ impl TextWrap {
}
ret
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
}
@ -417,14 +406,14 @@ impl ObjectSubclass for TextWrap {
TextWrap::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|textwrap, element| textwrap.sink_chain(pad, element, buffer),
|textwrap| textwrap.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
TextWrap::catch_panic_pad_function(
parent,
|| false,
|textwrap, element| textwrap.sink_event(pad, element, event),
|textwrap| textwrap.sink_event(pad, event),
)
})
.flags(gst::PadFlags::PROXY_CAPS | gst::PadFlags::FIXED_CAPS)
@ -436,7 +425,7 @@ impl ObjectSubclass for TextWrap {
TextWrap::catch_panic_pad_function(
parent,
|| false,
|textwrap, element| textwrap.src_query(pad, element, query),
|textwrap| textwrap.src_query(pad, query),
)
})
.flags(gst::PadFlags::PROXY_CAPS | gst::PadFlags::FIXED_CAPS)
@ -491,20 +480,15 @@ impl ObjectImpl for TextWrap {
PROPERTIES.as_ref()
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"dictionary" => {
let mut settings = self.settings.lock().unwrap();
@ -530,19 +514,23 @@ impl ObjectImpl for TextWrap {
if settings.accumulate_time != old_accumulate_time {
gst::debug!(
CAT,
obj: obj,
imp: self,
"Accumulate time changed: {}",
settings.accumulate_time.display(),
);
drop(settings);
let _ = obj.post_message(gst::message::Latency::builder().src(obj).build());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
}
}
_ => unimplemented!(),
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"dictionary" => {
let settings = self.settings.lock().unwrap();
@ -610,17 +598,16 @@ impl ElementImpl for TextWrap {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::info!(CAT, obj: element, "Changing state {:?}", transition);
gst::info!(CAT, imp: self, "Changing state {:?}", transition);
if let gst::StateChange::PausedToReady = transition {
let mut state = self.state.lock().unwrap();
*state = State::default();
}
let success = self.parent_change_state(element, transition)?;
let success = self.parent_change_state(transition)?;
Ok(success)
}

View file

@ -40,7 +40,6 @@ impl Identity {
fn sink_chain(
&self,
pad: &gst::Pad,
_element: &super::Identity,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@ -54,7 +53,7 @@ impl Identity {
//
// See the documentation of gst::Event and gst::EventRef to see what can be done with
// events, and especially the gst::EventView type for inspecting events.
fn sink_event(&self, pad: &gst::Pad, _element: &super::Identity, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
self.srcpad.push_event(event)
}
@ -68,12 +67,7 @@ impl Identity {
//
// See the documentation of gst::Query and gst::QueryRef to see what can be done with
// queries, and especially the gst::QueryView type for inspecting and modifying queries.
fn sink_query(
&self,
pad: &gst::Pad,
_element: &super::Identity,
query: &mut gst::QueryRef,
) -> bool {
fn sink_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
self.srcpad.peer_query(query)
}
@ -86,7 +80,7 @@ impl Identity {
//
// See the documentation of gst::Event and gst::EventRef to see what can be done with
// events, and especially the gst::EventView type for inspecting events.
fn src_event(&self, pad: &gst::Pad, _element: &super::Identity, event: gst::Event) -> bool {
fn src_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
self.sinkpad.push_event(event)
}
@ -100,12 +94,7 @@ impl Identity {
//
// See the documentation of gst::Query and gst::QueryRef to see what can be done with
// queries, and especially the gst::QueryView type for inspecting and modifying queries.
fn src_query(
&self,
pad: &gst::Pad,
_element: &super::Identity,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
self.sinkpad.peer_query(query)
}
@ -139,21 +128,21 @@ impl ObjectSubclass for Identity {
Identity::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|identity, element| identity.sink_chain(pad, element, buffer),
|identity| identity.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.sink_event(pad, element, event),
|identity| identity.sink_event(pad, event),
)
})
.query_function(|pad, parent, query| {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.sink_query(pad, element, query),
|identity| identity.sink_query(pad, query),
)
})
.build();
@ -164,14 +153,14 @@ impl ObjectSubclass for Identity {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.src_event(pad, element, event),
|identity| identity.src_event(pad, event),
)
})
.query_function(|pad, parent, query| {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.src_query(pad, element, query),
|identity| identity.src_query(pad, query),
)
})
.build();
@ -186,12 +175,13 @@ impl ObjectSubclass for Identity {
// Implementation of glib::Object virtual methods
impl ObjectImpl for Identity {
// Called right after construction of a new instance
fn constructed(&self, obj: &Self::Type) {
fn constructed(&self) {
// Call the parent class' ::constructed() implementation first
self.parent_constructed(obj);
self.parent_constructed();
// Here we actually add the pads we created in Identity::new() to the
// element so that GStreamer is aware of their existence.
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -255,12 +245,11 @@ impl ElementImpl for Identity {
// the element again.
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
// Call the parent class' implementation of ::change_state()
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -96,13 +96,7 @@ impl ObjectImpl for ProgressBin {
// Called whenever a value of a property is changed. It can be called
// at any time from any thread.
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"output" => {
let mut output_type = self.output_type.lock().unwrap();
@ -111,7 +105,7 @@ impl ObjectImpl for ProgressBin {
.expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing output from {:?} to {:?}",
output_type,
new_output_type
@ -124,7 +118,7 @@ impl ObjectImpl for ProgressBin {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"output" => {
let output_type = self.output_type.lock().unwrap();
@ -135,13 +129,15 @@ impl ObjectImpl for ProgressBin {
}
// Called right after construction of a new instance
fn constructed(&self, obj: &Self::Type) {
fn constructed(&self) {
// Call the parent class' ::constructed() implementation first
self.parent_constructed(obj);
self.parent_constructed();
// Here we actually add the pads we created in ProgressBin::new() to the
// element so that GStreamer is aware of their existence.
let obj = self.instance();
// Add the progressreport element to the bin.
obj.add(&self.progress).unwrap();
@ -215,7 +211,7 @@ impl ElementImpl for ProgressBin {
// Implementation of gst::Bin virtual methods
impl BinImpl for ProgressBin {
fn handle_message(&self, bin: &Self::Type, msg: gst::Message) {
fn handle_message(&self, msg: gst::Message) {
use gst::MessageView;
match msg.view() {
@ -236,12 +232,12 @@ impl BinImpl for ProgressBin {
match output_type {
ProgressBinOutput::Println => println!("progress: {:5.1}%", percent),
ProgressBinOutput::DebugCategory => {
gst::info!(CAT, "progress: {:5.1}%", percent);
gst::info!(CAT, imp: self, "progress: {:5.1}%", percent);
}
};
}
}
_ => self.parent_handle_message(bin, msg),
_ => self.parent_handle_message(msg),
}
}
}

View file

@ -119,20 +119,14 @@ impl ObjectImpl for Rgb2Gray {
// Called whenever a value of a property is changed. It can be called
// at any time from any thread.
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"invert" => {
let mut settings = self.settings.lock().unwrap();
let invert = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing invert from {} to {}",
settings.invert,
invert
@ -144,7 +138,7 @@ impl ObjectImpl for Rgb2Gray {
let shift = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing shift from {} to {}",
settings.shift,
shift
@ -157,7 +151,7 @@ impl ObjectImpl for Rgb2Gray {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"invert" => {
let settings = self.settings.lock().unwrap();
@ -281,7 +275,6 @@ impl BaseTransformImpl for Rgb2Gray {
// In our case that means that:
fn transform_caps(
&self,
element: &Self::Type,
direction: gst::PadDirection,
caps: &gst::Caps,
filter: Option<&gst::Caps>,
@ -320,7 +313,7 @@ impl BaseTransformImpl for Rgb2Gray {
gst::debug!(
CAT,
obj: element,
imp: self,
"Transformed caps from {} to {} in direction {:?}",
caps,
other_caps,
@ -341,7 +334,6 @@ impl VideoFilterImpl for Rgb2Gray {
// Does the actual transformation of the input buffer to the output buffer
fn transform_frame(
&self,
_element: &Self::Type,
in_frame: &gst_video::VideoFrameRef<&gst::BufferRef>,
out_frame: &mut gst_video::VideoFrameRef<&mut gst::BufferRef>,
) -> Result<gst::FlowSuccess, gst::FlowError> {

View file

@ -208,10 +208,11 @@ impl ObjectImpl for SineSrc {
}
// Called right after construction of a new instance
fn constructed(&self, obj: &Self::Type) {
fn constructed(&self) {
// Call the parent class' ::constructed() implementation first
self.parent_constructed(obj);
self.parent_constructed();
let obj = self.instance();
// Initialize live-ness and notify the base class that
// we'd like to operate in Time format
obj.set_live(DEFAULT_IS_LIVE);
@ -220,20 +221,14 @@ impl ObjectImpl for SineSrc {
// Called whenever a value of a property is changed. It can be called
// at any time from any thread.
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"samples-per-buffer" => {
let mut settings = self.settings.lock().unwrap();
let samples_per_buffer = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing samples-per-buffer from {} to {}",
settings.samples_per_buffer,
samples_per_buffer
@ -241,14 +236,18 @@ impl ObjectImpl for SineSrc {
settings.samples_per_buffer = samples_per_buffer;
drop(settings);
let _ = obj.post_message(gst::message::Latency::builder().src(obj).build());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
}
"freq" => {
let mut settings = self.settings.lock().unwrap();
let freq = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing freq from {} to {}",
settings.freq,
freq
@ -260,7 +259,7 @@ impl ObjectImpl for SineSrc {
let volume = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing volume from {} to {}",
settings.volume,
volume
@ -272,7 +271,7 @@ impl ObjectImpl for SineSrc {
let mute = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing mute from {} to {}",
settings.mute,
mute
@ -284,7 +283,7 @@ impl ObjectImpl for SineSrc {
let is_live = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing is-live from {} to {}",
settings.is_live,
is_live
@ -297,7 +296,7 @@ impl ObjectImpl for SineSrc {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"samples-per-buffer" => {
let settings = self.settings.lock().unwrap();
@ -386,16 +385,16 @@ impl ElementImpl for SineSrc {
// the element again.
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
// Configure live'ness once here just before starting the source
if let gst::StateChange::ReadyToPaused = transition {
element.set_live(self.settings.lock().unwrap().is_live);
self.instance()
.set_live(self.settings.lock().unwrap().is_live);
}
// Call the parent class' implementation of ::change_state()
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}
@ -407,16 +406,17 @@ impl BaseSrcImpl for SineSrc {
//
// We simply remember the resulting AudioInfo from the caps to be able to use this for knowing
// the sample rate, etc. when creating buffers
fn set_caps(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
fn set_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
use std::f64::consts::PI;
let info = gst_audio::AudioInfo::from_caps(caps).map_err(|_| {
gst::loggable_error!(CAT, "Failed to build `AudioInfo` from caps {}", caps)
})?;
gst::debug!(CAT, obj: element, "Configuring for caps {}", caps);
gst::debug!(CAT, imp: self, "Configuring for caps {}", caps);
element.set_blocksize(info.bpf() * (*self.settings.lock().unwrap()).samples_per_buffer);
self.instance()
.set_blocksize(info.bpf() * (*self.settings.lock().unwrap()).samples_per_buffer);
let settings = *self.settings.lock().unwrap();
let mut state = self.state.lock().unwrap();
@ -451,34 +451,38 @@ impl BaseSrcImpl for SineSrc {
drop(state);
let _ = element.post_message(gst::message::Latency::builder().src(element).build());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
Ok(())
}
// Called when starting, so we can initialize all stream-related state to its defaults
fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
// Reset state
*self.state.lock().unwrap() = Default::default();
self.unlock_stop(element)?;
self.unlock_stop()?;
gst::info!(CAT, obj: element, "Started");
gst::info!(CAT, imp: self, "Started");
Ok(())
}
// Called when shutting down the element so we can release all stream-related state
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
// Reset state
*self.state.lock().unwrap() = Default::default();
self.unlock(element)?;
self.unlock()?;
gst::info!(CAT, obj: element, "Stopped");
gst::info!(CAT, imp: self, "Stopped");
Ok(())
}
fn query(&self, element: &Self::Type, query: &mut gst::QueryRef) -> bool {
fn query(&self, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
match query.view_mut() {
@ -493,18 +497,18 @@ impl BaseSrcImpl for SineSrc {
let latency = gst::ClockTime::SECOND
.mul_div_floor(settings.samples_per_buffer as u64, info.rate() as u64)
.unwrap();
gst::debug!(CAT, obj: element, "Returning latency {}", latency);
gst::debug!(CAT, imp: self, "Returning latency {}", latency);
q.set(settings.is_live, latency, gst::ClockTime::NONE);
true
} else {
false
}
}
_ => BaseSrcImplExt::parent_query(self, element, query),
_ => BaseSrcImplExt::parent_query(self, query),
}
}
fn fixate(&self, element: &Self::Type, mut caps: gst::Caps) -> gst::Caps {
fn fixate(&self, mut caps: gst::Caps) -> gst::Caps {
// Fixate the caps. BaseSrc will do some fixation for us, but
// as we allow any rate between 1 and MAX it would fixate to 1. 1Hz
// is generally not a useful sample rate.
@ -522,14 +526,14 @@ impl BaseSrcImpl for SineSrc {
// Let BaseSrc fixate anything else for us. We could've alternatively have
// called caps.fixate() here
self.parent_fixate(element, caps)
self.parent_fixate(caps)
}
fn is_seekable(&self, _element: &Self::Type) -> bool {
fn is_seekable(&self) -> bool {
true
}
fn do_seek(&self, element: &Self::Type, segment: &mut gst::Segment) -> bool {
fn do_seek(&self, segment: &mut gst::Segment) -> bool {
// Handle seeking here. For Time and Default (sample offset) seeks we can
// do something and have to update our sample offset and accumulator accordingly.
//
@ -538,7 +542,7 @@ impl BaseSrcImpl for SineSrc {
// and for calculating the timestamps, etc.
if segment.rate() < 0.0 {
gst::error!(CAT, obj: element, "Reverse playback not supported");
gst::error!(CAT, imp: self, "Reverse playback not supported");
return false;
}
@ -572,7 +576,7 @@ impl BaseSrcImpl for SineSrc {
gst::debug!(
CAT,
obj: element,
imp: self,
"Seeked to {}-{:?} (accum: {}) for segment {:?}",
sample_offset,
sample_stop,
@ -594,7 +598,7 @@ impl BaseSrcImpl for SineSrc {
if state.info.is_none() {
gst::error!(
CAT,
obj: element,
imp: self,
"Can only seek in Default format if sample rate is known"
);
return false;
@ -608,7 +612,7 @@ impl BaseSrcImpl for SineSrc {
gst::debug!(
CAT,
obj: element,
imp: self,
"Seeked to {}-{:?} (accum: {}) for segment {:?}",
sample_offset,
sample_stop,
@ -627,7 +631,7 @@ impl BaseSrcImpl for SineSrc {
} else {
gst::error!(
CAT,
obj: element,
imp: self,
"Can't seek in format {:?}",
segment.format()
);
@ -636,10 +640,10 @@ impl BaseSrcImpl for SineSrc {
}
}
fn unlock(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn unlock(&self) -> Result<(), gst::ErrorMessage> {
// This should unblock the create() function ASAP, so we
// just unschedule the clock it here, if any.
gst::debug!(CAT, obj: element, "Unlocking");
gst::debug!(CAT, imp: self, "Unlocking");
let mut clock_wait = self.clock_wait.lock().unwrap();
if let Some(clock_id) = clock_wait.clock_id.take() {
clock_id.unschedule();
@ -649,10 +653,10 @@ impl BaseSrcImpl for SineSrc {
Ok(())
}
fn unlock_stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn unlock_stop(&self) -> Result<(), gst::ErrorMessage> {
// This signals that unlocking is done, so we can reset
// all values again.
gst::debug!(CAT, obj: element, "Unlock stop");
gst::debug!(CAT, imp: self, "Unlock stop");
let mut clock_wait = self.clock_wait.lock().unwrap();
clock_wait.flushing = false;
@ -664,7 +668,6 @@ impl PushSrcImpl for SineSrc {
// Creates the audio buffers
fn create(
&self,
element: &Self::Type,
_buffer: Option<&mut gst::BufferRef>,
) -> Result<CreateSuccess, gst::FlowError> {
// Keep a local copy of the values of all our properties at this very moment. This
@ -676,7 +679,7 @@ impl PushSrcImpl for SineSrc {
let mut state = self.state.lock().unwrap();
let info = match state.info {
None => {
gst::element_error!(element, gst::CoreError::Negotiation, ["Have no caps yet"]);
gst::element_imp_error!(self, gst::CoreError::Negotiation, ["Have no caps yet"]);
return Err(gst::FlowError::NotNegotiated);
}
Some(ref info) => info.clone(),
@ -686,7 +689,7 @@ impl PushSrcImpl for SineSrc {
// point but at most samples_per_buffer samples per buffer
let n_samples = if let Some(sample_stop) = state.sample_stop {
if sample_stop <= state.sample_offset {
gst::log!(CAT, obj: element, "At EOS");
gst::log!(CAT, imp: self, "At EOS");
return Err(gst::FlowError::Eos);
}
@ -754,14 +757,18 @@ impl PushSrcImpl for SineSrc {
// Waiting happens based on the pipeline clock, which means that a real live source
// with its own clock would require various translations between the two clocks.
// This is out of scope for the tutorial though.
if element.is_live() {
let clock = match element.clock() {
None => return Ok(CreateSuccess::NewBuffer(buffer)),
Some(clock) => clock,
};
if self.instance().is_live() {
let (clock, base_time) =
match Option::zip(self.instance().clock(), self.instance().base_time()) {
None => return Ok(CreateSuccess::NewBuffer(buffer)),
Some(res) => res,
};
let segment = element.segment().downcast::<gst::format::Time>().unwrap();
let base_time = element.base_time();
let segment = self
.instance()
.segment()
.downcast::<gst::format::Time>()
.unwrap();
let running_time = segment.to_running_time(buffer.pts().opt_add(buffer.duration()));
// The last sample's clock time is the base time of the element plus the
@ -776,7 +783,7 @@ impl PushSrcImpl for SineSrc {
// so that we immediately stop waiting on e.g. shutdown.
let mut clock_wait = self.clock_wait.lock().unwrap();
if clock_wait.flushing {
gst::debug!(CAT, obj: element, "Flushing");
gst::debug!(CAT, imp: self, "Flushing");
return Err(gst::FlowError::Flushing);
}
@ -786,24 +793,24 @@ impl PushSrcImpl for SineSrc {
gst::log!(
CAT,
obj: element,
imp: self,
"Waiting until {}, now {}",
wait_until,
clock.time().display(),
);
let (res, jitter) = id.wait();
gst::log!(CAT, obj: element, "Waited res {:?} jitter {}", res, jitter);
gst::log!(CAT, imp: self, "Waited res {:?} jitter {}", res, jitter);
self.clock_wait.lock().unwrap().clock_id.take();
// If the clock ID was unscheduled, unlock() was called
// and we should return Flushing immediately.
if res == Err(gst::ClockError::Unscheduled) {
gst::debug!(CAT, obj: element, "Flushing");
gst::debug!(CAT, imp: self, "Flushing");
return Err(gst::FlowError::Flushing);
}
}
gst::debug!(CAT, obj: element, "Produced buffer {:?}", buffer);
gst::debug!(CAT, imp: self, "Produced buffer {:?}", buffer);
Ok(CreateSuccess::NewBuffer(buffer))
}

View file

@ -416,7 +416,6 @@ Whenever input/output caps are configured on our element, the `set_caps` virtual
impl BaseTransformImpl for Rgb2Gray {
fn set_caps(
&self,
element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
@ -431,7 +430,7 @@ impl BaseTransformImpl for Rgb2Gray {
gst::debug!(
CAT,
obj: element,
imp: self,
"Configured for caps {} to {}",
incaps,
outcaps
@ -442,11 +441,11 @@ impl BaseTransformImpl for Rgb2Gray {
Ok(())
}
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
// Drop state
let _ = self.state.lock().unwrap().take();
gst::info!(CAT, obj: element, "Stopped");
gst::info!(CAT, imp: self, "Stopped");
Ok(())
}
@ -459,7 +458,7 @@ Next we have to provide information to the `BaseTransform` base class about the
```rust
impl BaseTransformImpl for Rgb2Gray {
fn get_unit_size(&self, _element: &Self::Type, caps: &gst::Caps) -> Option<usize> {
fn get_unit_size(&self, caps: &gst::Caps) -> Option<usize> {
gst_video::VideoInfo::from_caps(caps).map(|info| info.size())
}
}
@ -479,7 +478,6 @@ This has to be implemented in the `transform_caps` virtual method, and looks as
impl BaseTransformImpl for Rgb2Gray {
fn transform_caps(
&self,
element: &Self::Type,
direction: gst::PadDirection,
caps: &gst::Caps,
filter: Option<&gst::Caps>,
@ -511,7 +509,7 @@ impl BaseTransformImpl for Rgb2Gray {
gst::debug!(
CAT,
obj: element,
imp: self,
"Transformed caps from {} to {} in direction {:?}",
caps,
other_caps,
@ -569,21 +567,20 @@ Afterwards we have to actually call this function on every pixel. For this the t
impl BaseTransformImpl for Rgb2Gray {
fn transform(
&self,
element: &Self::Type,
inbuf: &gst::Buffer,
outbuf: &mut gst::BufferRef,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().ok_or_else(|| {
gst::element_error!(element, gst::CoreError::Negotiation, ["Have no state yet"]);
gst::element_imp_error!(self, gst::CoreError::Negotiation, ["Have no state yet"]);
gst::FlowError::NotNegotiated
})?;
let in_frame =
gst_video::VideoFrameRef::from_buffer_ref_readable(inbuf.as_ref(), &state.in_info)
.ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Failed,
["Failed to map input buffer readable"]
);
@ -593,8 +590,8 @@ impl BaseTransformImpl for Rgb2Gray {
let mut out_frame =
gst_video::VideoFrameRef::from_buffer_ref_writable(outbuf, &state.out_info)
.ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Failed,
["Failed to map output buffer writable"]
);
@ -761,14 +758,14 @@ In the next step we have to implement functions that are called whenever a prope
impl ObjectImpl for Rgb2Gray {
[...]
fn set_property(&self, obj: &Self::Type, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.get_name() {
"invert" => {
let mut settings = self.settings.lock().unwrap();
let invert = value.get_some().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing invert from {} to {}",
settings.invert,
invert
@ -780,7 +777,7 @@ impl ObjectImpl for Rgb2Gray {
let shift = value.get_some().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing shift from {} to {}",
settings.shift,
shift
@ -791,7 +788,7 @@ impl ObjectImpl for Rgb2Gray {
}
}
fn get_property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn get_property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.get_name() {
"invert" => {
let settings = self.settings.lock().unwrap();
@ -840,7 +837,6 @@ impl Rgb2Gray {
impl BaseTransformImpl for Rgb2Gray {
fn transform(
&self,
element: &Self::Type,
inbuf: &gst::Buffer,
outbuf: &mut gst::BufferRef,
) -> Result<gst::FlowSuccess, gst::FlowError> {

View file

@ -208,12 +208,13 @@ impl ObjectImpl for SineSrc {
}
// Called right after construction of a new instance
fn constructed(&self, obj: &Self::Type) {
fn constructed(&self) {
// Call the parent class' ::constructed() implementation first
self.parent_constructed(obj);
self.parent_constructed();
// Initialize live-ness and notify the base class that
// we'd like to operate in Time format
let obj = self.instance();
obj.set_live(DEFAULT_IS_LIVE);
obj.set_format(gst::Format::Time);
}
@ -222,7 +223,6 @@ impl ObjectImpl for SineSrc {
// at any time from any thread.
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
@ -233,7 +233,7 @@ impl ObjectImpl for SineSrc {
let samples_per_buffer = value.get_some().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing samples-per-buffer from {} to {}",
settings.samples_per_buffer,
samples_per_buffer
@ -241,14 +241,14 @@ impl ObjectImpl for SineSrc {
settings.samples_per_buffer = samples_per_buffer;
drop(settings);
let _ = obj.post_message(gst::message::Latency::builder().src(obj).build());
let _ = self.instance().post_message(gst::message::Latency::builder().src(&*self.instance()).build());
}
"freq" => {
let mut settings = self.settings.lock().unwrap();
let freq = value.get_some().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing freq from {} to {}",
settings.freq,
freq
@ -260,7 +260,7 @@ impl ObjectImpl for SineSrc {
let volume = value.get_some().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing volume from {} to {}",
settings.volume,
volume
@ -272,7 +272,7 @@ impl ObjectImpl for SineSrc {
let mute = value.get_some().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing mute from {} to {}",
settings.mute,
mute
@ -284,7 +284,7 @@ impl ObjectImpl for SineSrc {
let is_live = value.get_some().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing is-live from {} to {}",
settings.is_live,
is_live
@ -297,7 +297,7 @@ impl ObjectImpl for SineSrc {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
fn get_property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn get_property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.get_name() {
"samples-per-buffer" => {
let settings = self.settings.lock().unwrap();
@ -329,21 +329,21 @@ impl ElementImpl for SineSrc { }
impl BaseSrcImpl for SineSrc {
// Called when starting, so we can initialize all stream-related state to its defaults
fn start(&self, element: &Self::Type) -> bool {
fn start(&self) -> bool {
// Reset state
*self.state.lock().unwrap() = Default::default();
gst::info!(CAT, obj: element, "Started");
gst::info!(CAT, imp: self, "Started");
true
}
// Called when shutting down the element so we can release all stream-related state
fn stop(&self, element: &Self::Type) -> bool {
fn stop(&self) -> bool {
// Reset state
*self.state.lock().unwrap() = Default::default();
gst::info!(CAT, obj: element, "Stopped");
gst::info!(CAT, imp: self, "Stopped");
true
}
@ -400,16 +400,16 @@ The first part that we have to implement, just like last time, is caps negotiati
First of all, we need to get notified whenever the caps that our source is configured for are changing. This will happen once in the very beginning and then whenever the pipeline topology or state changes and new caps would be more optimal for the new situation. This notification happens via the `BaseTransform::set_caps` virtual method.
```rust
fn set_caps(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
fn set_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
use std::f64::consts::PI;
let info = gst_audio::AudioInfo::from_caps(caps).map_err(|_| {
gst::loggable_error!(CAT, "Failed to build `AudioInfo` from caps {}", caps)
})?;
gst::debug!(CAT, obj: element, "Configuring for caps {}", caps);
gst::debug!(CAT, imp: self, "Configuring for caps {}", caps);
element.set_blocksize(info.bpf() * (*self.settings.lock().unwrap()).samples_per_buffer);
self.instance().set_blocksize(info.bpf() * (*self.settings.lock().unwrap()).samples_per_buffer);
let settings = *self.settings.lock().unwrap();
let mut state = self.state.lock().unwrap();
@ -444,7 +444,7 @@ First of all, we need to get notified whenever the caps that our source is confi
drop(state);
let _ = element.post_message(&gst::Message::new_latency().src(Some(element)).build());
let _ = self.instance().post_message(&gst::Message::new_latency().src(Some(&*self.instance())).build());
Ok(())
}
@ -459,7 +459,7 @@ As a last step we post a new `LATENCY` message on the bus whenever the sample
`BaseSrc` is by default already selecting possible caps for us, if there are multiple options. However these defaults might not be (and often are not) ideal and we should override the default behaviour slightly. This is done in the `BaseSrc::fixate` virtual method.
```rust
fn fixate(&self, element: &Self::Type, mut caps: gst::Caps) -> gst::Caps {
fn fixate(&self, mut caps: gst::Caps) -> gst::Caps {
// Fixate the caps. BaseSrc will do some fixation for us, but
// as we allow any rate between 1 and MAX it would fixate to 1. 1Hz
// is generally not a useful sample rate.
@ -477,7 +477,7 @@ As a last step we post a new `LATENCY` message on the bus whenever the sample
// Let BaseSrc fixate anything else for us. We could've alternatively have
// called caps.fixate() here
element.parent_fixate(caps)
self.parent_fixate(caps)
}
```
@ -551,7 +551,6 @@ Now that this is done, we need to implement the `PushSrc::create` virtual meth
```rust
fn create(
&self,
element: &Self::Type,
) -> Result<gst::Buffer, gst::FlowReturn> {
// Keep a local copy of the values of all our properties at this very moment. This
// ensures that the mutex is never locked for long and the application wouldn't
@ -562,7 +561,7 @@ Now that this is done, we need to implement the `PushSrc::create` virtual meth
let mut state = self.state.lock().unwrap();
let info = match state.info {
None => {
gst::element_error!(element, gst::CoreError::Negotiation, ["Have no caps yet"]);
gst::element_imp_error!(self, gst::CoreError::Negotiation, ["Have no caps yet"]);
return Err(gst::FlowReturn::NotNegotiated);
}
Some(ref info) => info.clone(),
@ -572,7 +571,7 @@ Now that this is done, we need to implement the `PushSrc::create` virtual meth
// point but at most samples_per_buffer samples per buffer
let n_samples = if let Some(sample_stop) = state.sample_stop {
if sample_stop <= state.sample_offset {
gst::log!(CAT, obj: element, "At EOS");
gst::log!(CAT, imp: self, "At EOS");
return Err(gst::FlowReturn::Eos);
}
@ -631,7 +630,7 @@ Now that this is done, we need to implement the `PushSrc::create` virtual meth
state.sample_offset += n_samples;
drop(state);
gst::debug!(CAT, obj: element, "Produced buffer {:?}", buffer);
gst::debug!(CAT, imp: self, "Produced buffer {:?}", buffer);
Ok(buffer)
}
@ -700,7 +699,7 @@ For working in live mode, we have to add a few different parts in various places
gst::log!(
CAT,
obj: element,
imp: self,
"Waiting until {}, now {}",
wait_until,
clock.get_time().display(),
@ -708,14 +707,14 @@ For working in live mode, we have to add a few different parts in various places
let (res, jitter) = id.wait();
gst::log!(
CAT,
obj: element,
imp: self,
"Waited res {:?} jitter {}",
res,
jitter
);
}
gst::debug!(CAT, obj: element, "Produced buffer {:?}", buffer);
gst::debug!(CAT, imp: self, "Produced buffer {:?}", buffer);
Ok(buffer)
}
@ -733,7 +732,6 @@ Now we also have to tell the base class that we're running in live mode now. Thi
impl ElementImpl for SineSrc {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> gst::StateChangeReturn {
// Configure live'ness once here just before starting the source
@ -744,7 +742,7 @@ impl ElementImpl for SineSrc {
_ => (),
}
element.parent_change_state(transition)
self.parent_change_state(transition)
}
}
```
@ -754,7 +752,7 @@ And as a last step, we also need to notify downstream elements about our [laten
This querying is done with the `LATENCY` query, which we will have to handle in the `BaseSrc::query()` function.
```rust
fn query(&self, element: &Self::Type, query: &mut gst::QueryRef) -> bool {
fn query(&self, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
match query.view_mut() {
@ -769,14 +767,14 @@ This querying is done with the `LATENCY` query, which we will have to handle i
let latency = gst::ClockTime::SECOND
.mul_div_floor(settings.samples_per_buffer as u64, info.rate() as u64)
.unwrap();
gst::debug!(CAT, obj: element, "Returning latency {}", latency);
gst::debug!(CAT, imp: self, "Returning latency {}", latency);
q.set(settings.is_live, latency, gst::ClockTime::NONE);
true
} else {
false
}
}
_ => BaseSrcImplExt::parent_query(self, element, query),
_ => BaseSrcImplExt::parent_query(self, query),
}
}
@ -820,10 +818,10 @@ struct SineSrc {
[...]
fn unlock(&self, element: &Self::Type) -> bool {
fn unlock(&self) -> bool {
// This should unblock the create() function ASAP, so we
// just unschedule the clock it here, if any.
gst::debug!(CAT, obj: element, "Unlocking");
gst::debug!(CAT, imp: self, "Unlocking");
let mut clock_wait = self.clock_wait.lock().unwrap();
if let Some(clock_id) = clock_wait.clock_id.take() {
clock_id.unschedule();
@ -839,10 +837,10 @@ We store the clock ID in our struct, together with a boolean to signal whether w
Once everything is unlocked, we need to reset things again so that data flow can happen in the future. This is done in the `unlock_stop` virtual method.
```rust
fn unlock_stop(&self, element: &Self::Type) -> bool {
fn unlock_stop(&self) -> bool {
// This signals that unlocking is done, so we can reset
// all values again.
gst::debug!(CAT, obj: element, "Unlock stop");
gst::debug!(CAT, imp: self, "Unlock stop");
let mut clock_wait = self.clock_wait.lock().unwrap();
clock_wait.flushing = false;
@ -860,7 +858,7 @@ Now as a last step, we need to actually make use of the new struct we added arou
// so that we immediately stop waiting on e.g. shutdown.
let mut clock_wait = self.clock_wait.lock().unwrap();
if clock_wait.flushing {
gst::debug!(CAT, obj: element, "Flushing");
gst::debug!(CAT, imp: self, "Flushing");
return Err(gst::FlowReturn::Flushing);
}
@ -870,7 +868,7 @@ Now as a last step, we need to actually make use of the new struct we added arou
gst::log!(
CAT,
obj: element,
imp: self,
"Waiting until {}, now {}",
wait_until,
clock.get_time().display(),
@ -878,7 +876,7 @@ Now as a last step, we need to actually make use of the new struct we added arou
let (res, jitter) = id.wait();
gst::log!(
CAT,
obj: element,
imp: self,
"Waited res {:?} jitter {}",
res,
jitter
@ -888,7 +886,7 @@ Now as a last step, we need to actually make use of the new struct we added arou
// If the clock ID was unscheduled, unlock() was called
// and we should return Flushing immediately.
if res == gst::ClockReturn::Unscheduled {
gst::debug!(CAT, obj: element, "Flushing");
gst::debug!(CAT, imp: self, "Flushing");
return Err(gst::FlowReturn::Flushing);
}
```
@ -904,11 +902,11 @@ As a last feature we implement seeking on our source element. In our case that o
Seeking is implemented in the `BaseSrc::do_seek` virtual method, and signalling whether we can actually seek in the `is_seekable` virtual method.
```rust
fn is_seekable(&self, _element: &Self::Type) -> bool {
fn is_seekable(&self) -> bool {
true
}
fn do_seek(&self, element: &Self::Type, segment: &mut gst::Segment) -> bool {
fn do_seek(&self, segment: &mut gst::Segment) -> bool {
// Handle seeking here. For Time and Default (sample offset) seeks we can
// do something and have to update our sample offset and accumulator accordingly.
//
@ -917,7 +915,7 @@ Seeking is implemented in the `BaseSrc::do_seek` virtual method, and signallin
// and for calculating the timestamps, etc.
if segment.get_rate() < 0.0 {
gst::error!(CAT, obj: element, "Reverse playback not supported");
gst::error!(CAT, imp: self, "Reverse playback not supported");
return false;
}
@ -950,7 +948,7 @@ Seeking is implemented in the `BaseSrc::do_seek` virtual method, and signallin
gst::debug!(
CAT,
obj: element,
imp: self,
"Seeked to {}-{:?} (accum: {}) for segment {:?}",
sample_offset,
sample_stop,
@ -972,7 +970,7 @@ Seeking is implemented in the `BaseSrc::do_seek` virtual method, and signallin
if state.info.is_none() {
gst::error!(
CAT,
obj: element,
imp: self,
"Can only seek in Default format if sample rate is known"
);
return false;
@ -986,7 +984,7 @@ Seeking is implemented in the `BaseSrc::do_seek` virtual method, and signallin
gst::debug!(
CAT,
obj: element,
imp: self,
"Seeked to {}-{:?} (accum: {}) for segment {:?}",
sample_offset,
sample_stop,
@ -1005,7 +1003,7 @@ Seeking is implemented in the `BaseSrc::do_seek` virtual method, and signallin
} else {
gst::error!(
CAT,
obj: element,
imp: self,
"Can't seek in format {:?}",
segment.get_format()
);

View file

@ -68,26 +68,21 @@ impl ObjectImpl for CustomSource {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"source" => {
let source = value.get::<gst::Element>().unwrap();
self.source.set(source.clone()).unwrap();
obj.add(&source).unwrap();
self.instance().add(&source).unwrap();
}
_ => unreachable!(),
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.set_suppressed_flags(gst::ElementFlags::SOURCE | gst::ElementFlags::SINK);
obj.set_element_flags(gst::ElementFlags::SOURCE);
obj.set_bin_flags(gst::BinFlags::STREAMS_AWARE);
@ -124,21 +119,20 @@ impl ElementImpl for CustomSource {
#[allow(clippy::single_match)]
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
match transition {
gst::StateChange::NullToReady => {
self.start(element)?;
self.start()?;
}
_ => (),
}
let res = self.parent_change_state(element, transition)?;
let res = self.parent_change_state(transition)?;
match transition {
gst::StateChange::ReadyToNull | gst::StateChange::NullToNull => {
self.stop(element);
self.stop();
}
_ => (),
}
@ -149,7 +143,7 @@ impl ElementImpl for CustomSource {
impl BinImpl for CustomSource {
#[allow(clippy::single_match)]
fn handle_message(&self, bin: &Self::Type, msg: gst::Message) {
fn handle_message(&self, msg: gst::Message) {
use gst::MessageView;
match msg.view() {
@ -157,19 +151,16 @@ impl BinImpl for CustomSource {
// TODO: Drop stream collection message for now, we only create a simple custom
// one here so that fallbacksrc can know about our streams. It is never
// forwarded.
self.handle_source_no_more_pads(bin);
self.handle_source_no_more_pads();
}
_ => self.parent_handle_message(bin, msg),
_ => self.parent_handle_message(msg),
}
}
}
impl CustomSource {
fn start(
&self,
element: &super::CustomSource,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::debug!(CAT, obj: element, "Starting");
fn start(&self) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::debug!(CAT, imp: self, "Starting");
let source = self.source.get().unwrap();
let templates = source.pad_template_list();
@ -178,9 +169,9 @@ impl CustomSource {
.iter()
.any(|templ| templ.presence() == gst::PadPresence::Request)
{
gst::error!(CAT, obj: element, "Request pads not supported");
gst::element_error!(
element,
gst::error!(CAT, imp: self, "Request pads not supported");
gst::element_imp_error!(
self,
gst::LibraryError::Settings,
["Request pads not supported"]
);
@ -193,49 +184,55 @@ impl CustomSource {
// Handle all source pads that already exist
for pad in source.src_pads() {
if let Err(msg) = self.handle_source_pad_added(element, &pad) {
element.post_error_message(msg);
if let Err(msg) = self.handle_source_pad_added(&pad) {
self.post_error_message(msg);
return Err(gst::StateChangeError);
}
}
if !has_sometimes_pads {
self.handle_source_no_more_pads(element);
self.handle_source_no_more_pads();
} else {
gst::debug!(CAT, obj: element, "Found sometimes pads");
gst::debug!(CAT, imp: self, "Found sometimes pads");
let element_weak = element.downgrade();
let pad_added_sig_id = source.connect_pad_added(move |_, pad| {
let element = match element_weak.upgrade() {
None => return,
let pad_added_sig_id = source.connect_pad_added(move |source, pad| {
let element = match source
.parent()
.and_then(|p| p.downcast::<super::CustomSource>().ok())
{
Some(element) => element,
None => return,
};
let src = element.imp();
if let Err(msg) = src.handle_source_pad_added(&element, pad) {
if let Err(msg) = src.handle_source_pad_added(pad) {
element.post_error_message(msg);
}
});
let element_weak = element.downgrade();
let pad_removed_sig_id = source.connect_pad_removed(move |_, pad| {
let element = match element_weak.upgrade() {
None => return,
let pad_removed_sig_id = source.connect_pad_removed(move |source, pad| {
let element = match source
.parent()
.and_then(|p| p.downcast::<super::CustomSource>().ok())
{
Some(element) => element,
None => return,
};
let src = element.imp();
src.handle_source_pad_removed(&element, pad);
src.handle_source_pad_removed(pad);
});
let element_weak = element.downgrade();
let no_more_pads_sig_id = source.connect_no_more_pads(move |_| {
let element = match element_weak.upgrade() {
None => return,
let no_more_pads_sig_id = source.connect_no_more_pads(move |source| {
let element = match source
.parent()
.and_then(|p| p.downcast::<super::CustomSource>().ok())
{
Some(element) => element,
None => return,
};
let src = element.imp();
src.handle_source_no_more_pads(&element);
src.handle_source_no_more_pads();
});
let mut state = self.state.lock().unwrap();
@ -247,12 +244,8 @@ impl CustomSource {
Ok(gst::StateChangeSuccess::Success)
}
fn handle_source_pad_added(
&self,
element: &super::CustomSource,
pad: &gst::Pad,
) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, obj: element, "Source added pad {}", pad.name());
fn handle_source_pad_added(&self, pad: &gst::Pad) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Source added pad {}", pad.name());
let mut state = self.state.lock().unwrap();
@ -268,7 +261,7 @@ impl CustomSource {
let caps = match pad.current_caps().unwrap_or_else(|| pad.query_caps(None)) {
caps if !caps.is_any() && !caps.is_empty() => caps,
_ => {
gst::error!(CAT, obj: element, "Pad {} had no caps", pad.name());
gst::error!(CAT, imp: self, "Pad {} had no caps", pad.name());
return Err(gst::error_msg!(
gst::CoreError::Negotiation,
["Pad had no caps"]
@ -292,11 +285,11 @@ impl CustomSource {
let (templ, name) = if stream_type.contains(gst::StreamType::AUDIO) {
let name = format!("audio_{}", state.num_audio);
state.num_audio += 1;
(element.pad_template("audio_%u").unwrap(), name)
(self.instance().pad_template("audio_%u").unwrap(), name)
} else {
let name = format!("video_{}", state.num_video);
state.num_video += 1;
(element.pad_template("video_%u").unwrap(), name)
(self.instance().pad_template("video_%u").unwrap(), name)
};
let ghost_pad = gst::GhostPad::builder_with_template(&templ, Some(&name))
@ -313,13 +306,13 @@ impl CustomSource {
drop(state);
ghost_pad.set_active(true).unwrap();
element.add_pad(&ghost_pad).unwrap();
self.instance().add_pad(&ghost_pad).unwrap();
Ok(())
}
fn handle_source_pad_removed(&self, element: &super::CustomSource, pad: &gst::Pad) {
gst::debug!(CAT, obj: element, "Source removed pad {}", pad.name());
fn handle_source_pad_removed(&self, pad: &gst::Pad) {
gst::debug!(CAT, imp: self, "Source removed pad {}", pad.name());
let mut state = self.state.lock().unwrap();
let (i, stream) = match state
@ -338,11 +331,11 @@ impl CustomSource {
ghost_pad.set_active(false).unwrap();
let _ = ghost_pad.set_target(None::<&gst::Pad>);
let _ = element.remove_pad(&ghost_pad);
let _ = self.instance().remove_pad(&ghost_pad);
}
fn handle_source_no_more_pads(&self, element: &super::CustomSource) {
gst::debug!(CAT, obj: element, "Source signalled no-more-pads");
fn handle_source_no_more_pads(&self) {
gst::debug!(CAT, imp: self, "Source signalled no-more-pads");
let state = self.state.lock().unwrap();
let streams = state
@ -355,17 +348,17 @@ impl CustomSource {
.build();
drop(state);
element.no_more_pads();
self.instance().no_more_pads();
let _ = element.post_message(
let _ = self.instance().post_message(
gst::message::StreamsSelected::builder(&collection)
.src(element)
.src(&*self.instance())
.build(),
);
}
fn stop(&self, element: &super::CustomSource) {
gst::debug!(CAT, obj: element, "Stopping");
fn stop(&self) {
gst::debug!(CAT, imp: self, "Stopping");
let mut state = self.state.lock().unwrap();
let source = self.source.get().unwrap();
@ -388,7 +381,7 @@ impl CustomSource {
for pad in pads {
let _ = pad.ghost_pad.set_target(None::<&gst::Pad>);
let _ = element.remove_pad(&pad.ghost_pad);
let _ = self.instance().remove_pad(&pad.ghost_pad);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -153,13 +153,7 @@ impl ObjectImpl for FallbackSwitchSinkPad {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
PROP_PRIORITY => {
let mut settings = self.settings.lock();
@ -170,7 +164,7 @@ impl ObjectImpl for FallbackSwitchSinkPad {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
PROP_PRIORITY => {
let settings = self.settings.lock();
@ -318,15 +312,15 @@ impl SinkState {
fn schedule_clock(
&mut self,
element: &super::FallbackSwitch,
imp: &FallbackSwitch,
pad: &super::FallbackSwitchSinkPad,
running_time: Option<gst::ClockTime>,
extra_time: gst::ClockTime,
) -> Option<gst::SingleShotClockId> {
let running_time = running_time?;
let clock = element.clock()?;
let clock = imp.instance().clock()?;
let base_time = imp.instance().base_time()?;
let base_time = element.base_time()?;
let wait_until = running_time + base_time;
let wait_until = wait_until.saturating_add(extra_time);
@ -403,15 +397,10 @@ impl FallbackSwitch {
debug!(CAT, obj: pad, "Now active pad");
}
fn handle_timeout(
&self,
element: &super::FallbackSwitch,
state: &mut State,
settings: &Settings,
) {
fn handle_timeout(&self, state: &mut State, settings: &Settings) {
debug!(
CAT,
obj: element,
imp: self,
"timeout fired - looking for a pad to switch to"
);
@ -423,10 +412,10 @@ impl FallbackSwitch {
let mut best_priority = 0u32;
let mut best_pad = None;
for pad in element.sink_pads() {
for pad in self.instance().sink_pads() {
/* Don't consider the active sinkpad */
let pad = pad.downcast_ref::<super::FallbackSwitchSinkPad>().unwrap();
let pad_imp = FallbackSwitchSinkPad::from_instance(pad);
let pad_imp = pad.imp();
if active_sinkpad.as_ref() == Some(pad) {
continue;
}
@ -446,7 +435,7 @@ impl FallbackSwitch {
if let Some(best_pad) = best_pad {
debug!(
CAT,
obj: element,
imp: self,
"Found viable pad to switch to: {:?}",
best_pad
);
@ -456,49 +445,44 @@ impl FallbackSwitch {
}
}
fn on_timeout(
&self,
element: &super::FallbackSwitch,
clock_id: &gst::ClockId,
settings: &Settings,
) {
fn on_timeout(&self, clock_id: &gst::ClockId, settings: &Settings) {
let mut state = self.state.lock();
if state.timeout_clock_id.as_ref() != Some(clock_id) {
/* Timeout fired late, ignore it. */
debug!(CAT, obj: element, "Late timeout callback. Ignoring");
debug!(CAT, imp: self, "Late timeout callback. Ignoring");
return;
}
// Ensure sink_chain on an inactive pad can schedule another timeout
state.timeout_clock_id = None;
self.handle_timeout(element, &mut state, settings);
self.handle_timeout(&mut state, settings);
}
fn cancel_waits(&self, element: &super::FallbackSwitch) {
for pad in element.sink_pads() {
let sink_pad = FallbackSwitchSinkPad::from_instance(pad.downcast_ref().unwrap());
let mut pad_state = sink_pad.state.lock();
fn cancel_waits(&self) {
for pad in self.instance().sink_pads() {
let pad = pad.downcast_ref::<super::FallbackSwitchSinkPad>().unwrap();
let pad_imp = pad.imp();
let mut pad_state = pad_imp.state.lock();
pad_state.cancel_wait();
}
}
fn schedule_timeout(
&self,
element: &super::FallbackSwitch,
state: &mut State,
settings: &Settings,
running_time: gst::ClockTime,
) {
state.cancel_timeout();
let clock = match element.clock() {
let clock = match self.instance().clock() {
None => return,
Some(clock) => clock,
};
let base_time = match element.base_time() {
let base_time = match self.instance().base_time() {
Some(base_time) => base_time,
None => return,
};
@ -511,26 +495,25 @@ impl FallbackSwitch {
/* If we're already running behind, fire the timeout immediately */
let now = clock.time();
if now.map_or(false, |now| wait_until <= now) {
self.handle_timeout(element, state, settings);
self.handle_timeout(state, settings);
return;
}
debug!(CAT, obj: element, "Scheduling timeout for {}", wait_until);
debug!(CAT, imp: self, "Scheduling timeout for {}", wait_until);
let timeout_id = clock.new_single_shot_id(wait_until);
state.timeout_clock_id = Some(timeout_id.clone().into());
state.timed_out = false;
let element_weak = element.downgrade();
let imp_weak = self.downgrade();
timeout_id
.wait_async(move |_clock, _time, clock_id| {
let element = match element_weak.upgrade() {
let imp = match imp_weak.upgrade() {
None => return,
Some(element) => element,
Some(imp) => imp,
};
let fallbackswitch = FallbackSwitch::from_instance(&element);
let settings = fallbackswitch.settings.lock().clone();
fallbackswitch.on_timeout(&element, clock_id, &settings);
let settings = imp.settings.lock().clone();
imp.on_timeout(clock_id, &settings);
})
.expect("Failed to wait async");
}
@ -553,23 +536,21 @@ impl FallbackSwitch {
fn sink_chain(
&self,
pad: &super::FallbackSwitchSinkPad,
element: &super::FallbackSwitch,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
self.chain(pad, element, buffer, None)
self.chain(pad, buffer, None)
}
fn chain(
&self,
pad: &super::FallbackSwitchSinkPad,
element: &super::FallbackSwitch,
buffer: gst::Buffer,
from_gap: Option<&gst::event::Gap>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state = self.state.lock();
let settings = self.settings.lock().clone();
let pad = pad.downcast_ref().unwrap();
let pad_imp = FallbackSwitchSinkPad::from_instance(pad);
let pad = pad.downcast_ref::<super::FallbackSwitchSinkPad>().unwrap();
let pad_imp = pad.imp();
let mut buffer = {
let pad_state = pad_imp.state.lock();
@ -654,7 +635,7 @@ impl FallbackSwitch {
#[allow(clippy::blocks_in_if_conditions)]
let output_clockid = if is_active {
pad_state.schedule_clock(
element,
self,
pad,
start_running_time,
state.upstream_latency + settings.latency,
@ -684,7 +665,7 @@ impl FallbackSwitch {
}
} else {
pad_state.schedule_clock(
element,
self,
pad,
end_running_time,
state.upstream_latency + settings.timeout + settings.latency,
@ -701,7 +682,7 @@ impl FallbackSwitch {
if let Some(running_time) = start_running_time {
if state.timeout_clock_id.is_none() && !is_active {
// May change active pad immediately
self.schedule_timeout(element, &mut state, &settings, running_time);
self.schedule_timeout(&mut state, &settings, running_time);
is_active = self.active_sinkpad.lock().as_ref() == Some(pad);
}
}
@ -716,7 +697,7 @@ impl FallbackSwitch {
let mut pad_state = pad_imp.state.lock();
if pad_state.flushing {
debug!(CAT, obj: element, "Flushing");
debug!(CAT, imp: self, "Flushing");
return Err(gst::FlowError::Flushing);
}
@ -756,7 +737,7 @@ impl FallbackSwitch {
if let Some(end_running_time) = end_running_time {
// May change active pad immediately
self.schedule_timeout(element, &mut state, &settings, end_running_time);
self.schedule_timeout(&mut state, &settings, end_running_time);
is_active = self.active_sinkpad.lock().as_ref() == Some(pad);
} else {
state.cancel_timeout();
@ -796,7 +777,7 @@ impl FallbackSwitch {
std::ops::ControlFlow::Continue(gst::EventForeachAction::Keep)
});
element.notify(PROP_ACTIVE_PAD);
self.instance().notify(PROP_ACTIVE_PAD);
}
if discont_pending && !buffer.flags().contains(gst::BufferFlags::DISCONT) {
@ -836,25 +817,19 @@ impl FallbackSwitch {
fn sink_chain_list(
&self,
pad: &super::FallbackSwitchSinkPad,
element: &super::FallbackSwitch,
list: gst::BufferList,
) -> Result<gst::FlowSuccess, gst::FlowError> {
log!(CAT, obj: pad, "Handling buffer list {:?}", list);
// TODO: Keep the list intact and forward it in one go (or broken into several
// pieces if needed) when outputting to the active pad
for buffer in list.iter_owned() {
self.chain(pad, element, buffer, None)?;
self.chain(pad, buffer, None)?;
}
Ok(gst::FlowSuccess::Ok)
}
fn sink_event(
&self,
pad: &super::FallbackSwitchSinkPad,
element: &super::FallbackSwitch,
event: gst::Event,
) -> bool {
fn sink_event(&self, pad: &super::FallbackSwitchSinkPad, event: gst::Event) -> bool {
if let gst::EventView::Gap(ev) = event.view() {
let mut buffer = gst::Buffer::new();
@ -866,7 +841,7 @@ impl FallbackSwitch {
buf_mut.set_duration(duration);
}
return match self.chain(pad, element, buffer, Some(ev)) {
return match self.chain(pad, buffer, Some(ev)) {
Ok(_) => true,
Err(gst::FlowError::Flushing) | Err(gst::FlowError::Eos) => true,
Err(err) => {
@ -900,8 +875,8 @@ impl FallbackSwitch {
gst::EventView::Segment(e) => {
let segment = match e.segment().clone().downcast::<gst::ClockTime>() {
Err(segment) => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Only TIME segments supported, got {:?}", segment.format(),]
);
@ -956,17 +931,12 @@ impl FallbackSwitch {
std::ops::ControlFlow::Continue(gst::EventForeachAction::Keep)
});
element.notify(PROP_ACTIVE_PAD);
self.instance().notify(PROP_ACTIVE_PAD);
}
self.src_pad.push_event(event)
}
fn sink_query(
&self,
pad: &super::FallbackSwitchSinkPad,
element: &super::FallbackSwitch,
query: &mut gst::QueryRef,
) -> bool {
fn sink_query(&self, pad: &super::FallbackSwitchSinkPad, query: &mut gst::QueryRef) -> bool {
use gst::QueryView;
log!(CAT, obj: pad, "Handling query {:?}", query);
@ -983,7 +953,7 @@ impl FallbackSwitch {
self.active_sinkpad.lock().as_ref() == Some(pad)
}
_ => {
pad.query_default(Some(element), query);
pad.query_default(Some(&*self.instance()), query);
false
}
};
@ -996,18 +966,13 @@ impl FallbackSwitch {
}
}
fn reset(&self, _element: &super::FallbackSwitch) {
fn reset(&self) {
let mut state = self.state.lock();
*state = State::default();
self.active_sinkpad.lock().take();
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::FallbackSwitch,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
log!(CAT, obj: pad, "Handling {:?}", query);
@ -1018,7 +983,7 @@ impl FallbackSwitch {
let mut min_latency = gst::ClockTime::ZERO;
let mut max_latency = gst::ClockTime::NONE;
for pad in element.sink_pads() {
for pad in self.instance().sink_pads() {
let mut peer_query = gst::query::Latency::new();
ret = pad.peer_query(&mut peer_query);
@ -1052,7 +1017,7 @@ impl FallbackSwitch {
if let Some(sinkpad) = sinkpad {
sinkpad.peer_query(query)
} else {
pad.query_default(Some(element), query)
pad.query_default(Some(&*self.instance()), query)
}
}
_ => {
@ -1083,7 +1048,7 @@ impl ObjectSubclass for FallbackSwitch {
FallbackSwitch::catch_panic_pad_function(
parent,
|| false,
|fallbackswitch, element| fallbackswitch.src_query(pad, element, query),
|fallbackswitch| fallbackswitch.src_query(pad, query),
)
})
.build();
@ -1146,20 +1111,14 @@ impl ObjectImpl for FallbackSwitch {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
PROP_ACTIVE_PAD => {
let settings = self.settings.lock();
if settings.auto_switch {
gst::warning!(
CAT,
obj: obj,
imp: self,
"active-pad property setting ignored, because auto-switch=true"
);
} else {
@ -1183,9 +1142,13 @@ impl ObjectImpl for FallbackSwitch {
let new_value = value.get().expect("type checked upstream");
settings.timeout = new_value;
debug!(CAT, obj: obj, "Timeout now {}", settings.timeout);
debug!(CAT, imp: self, "Timeout now {}", settings.timeout);
drop(settings);
let _ = obj.post_message(gst::message::Latency::builder().src(obj).build());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
}
PROP_LATENCY => {
let mut settings = self.settings.lock();
@ -1193,7 +1156,11 @@ impl ObjectImpl for FallbackSwitch {
settings.latency = new_value;
drop(settings);
let _ = obj.post_message(gst::message::Latency::builder().src(obj).build());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
}
PROP_MIN_UPSTREAM_LATENCY => {
let mut settings = self.settings.lock();
@ -1201,7 +1168,11 @@ impl ObjectImpl for FallbackSwitch {
settings.min_upstream_latency = new_value;
drop(settings);
let _ = obj.post_message(gst::message::Latency::builder().src(obj).build());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
}
PROP_IMMEDIATE_FALLBACK => {
let mut settings = self.settings.lock();
@ -1217,7 +1188,7 @@ impl ObjectImpl for FallbackSwitch {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
PROP_ACTIVE_PAD => {
let active_pad = self.active_sinkpad.lock().clone();
@ -1247,9 +1218,10 @@ impl ObjectImpl for FallbackSwitch {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.src_pad).unwrap();
obj.set_element_flags(gst::ElementFlags::REQUIRE_CLOCK);
}
@ -1297,23 +1269,22 @@ impl ElementImpl for FallbackSwitch {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
trace!(CAT, obj: element, "Changing state {:?}", transition);
trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::PlayingToPaused => {
self.cancel_waits(element);
self.cancel_waits();
}
gst::StateChange::ReadyToNull => {
self.reset(element);
self.reset();
}
gst::StateChange::ReadyToPaused => {
let mut state = self.state.lock();
let prev_active_pad = self.active_sinkpad.lock().take();
*state = State::default();
let pads = element.sink_pads();
let pads = self.instance().sink_pads();
if let Some(pad) = pads.first() {
let pad = pad.downcast_ref::<super::FallbackSwitchSinkPad>().unwrap();
@ -1324,7 +1295,7 @@ impl ElementImpl for FallbackSwitch {
drop(state);
if prev_active_pad.as_ref() != Some(pad) {
element.notify(PROP_ACTIVE_PAD);
self.instance().notify(PROP_ACTIVE_PAD);
}
}
for pad in pads {
@ -1336,7 +1307,7 @@ impl ElementImpl for FallbackSwitch {
_ => (),
}
let mut success = self.parent_change_state(element, transition)?;
let mut success = self.parent_change_state(transition)?;
match transition {
gst::StateChange::ReadyToPaused => {
@ -1347,7 +1318,7 @@ impl ElementImpl for FallbackSwitch {
}
gst::StateChange::PausedToReady => {
*self.state.lock() = State::default();
for pad in element.sink_pads() {
for pad in self.instance().sink_pads() {
let pad = pad.downcast_ref::<super::FallbackSwitchSinkPad>().unwrap();
let pad_imp = pad.imp();
*pad_imp.state.lock() = SinkState::default();
@ -1361,7 +1332,6 @@ impl ElementImpl for FallbackSwitch {
fn request_new_pad(
&self,
element: &Self::Type,
templ: &gst::PadTemplate,
_name: Option<String>,
_caps: Option<&gst::Caps>,
@ -1378,28 +1348,28 @@ impl ElementImpl for FallbackSwitch {
FallbackSwitch::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|fallbackswitch, element| fallbackswitch.sink_chain(pad, element, buffer),
|fallbackswitch| fallbackswitch.sink_chain(pad, buffer),
)
})
.chain_list_function(|pad, parent, bufferlist| {
FallbackSwitch::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|fallbackswitch, element| fallbackswitch.sink_chain_list(pad, element, bufferlist),
|fallbackswitch| fallbackswitch.sink_chain_list(pad, bufferlist),
)
})
.event_function(|pad, parent, event| {
FallbackSwitch::catch_panic_pad_function(
parent,
|| false,
|fallbackswitch, element| fallbackswitch.sink_event(pad, element, event),
|fallbackswitch| fallbackswitch.sink_event(pad, event),
)
})
.query_function(|pad, parent, query| {
FallbackSwitch::catch_panic_pad_function(
parent,
|| false,
|fallbackswitch, element| fallbackswitch.sink_query(pad, element, query),
|fallbackswitch| fallbackswitch.sink_query(pad, query),
)
})
.activatemode_function(|pad, _parent, mode, activate| {
@ -1408,7 +1378,7 @@ impl ElementImpl for FallbackSwitch {
.build();
pad.set_active(true).unwrap();
element.add_pad(&pad).unwrap();
self.instance().add_pad(&pad).unwrap();
let notify_active_pad = match &mut *self.active_sinkpad.lock() {
active_sinkpad @ None => {
@ -1426,26 +1396,34 @@ impl ElementImpl for FallbackSwitch {
drop(state);
if notify_active_pad {
element.notify(PROP_ACTIVE_PAD);
self.instance().notify(PROP_ACTIVE_PAD);
}
let _ = element.post_message(gst::message::Latency::builder().src(element).build());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
element.child_added(&pad, &pad.name());
self.instance().child_added(&pad, &pad.name());
Some(pad.upcast())
}
fn release_pad(&self, element: &Self::Type, pad: &gst::Pad) {
fn release_pad(&self, pad: &gst::Pad) {
let pad = pad.downcast_ref::<super::FallbackSwitchSinkPad>().unwrap();
let mut pad_state = pad.imp().state.lock();
pad_state.flush_start();
drop(pad_state);
let _ = pad.set_active(false);
element.remove_pad(pad).unwrap();
self.instance().remove_pad(pad).unwrap();
element.child_removed(pad, &pad.name());
let _ = element.post_message(gst::message::Latency::builder().src(element).build());
self.instance().child_removed(pad, &pad.name());
let _ = self.instance().post_message(
gst::message::Latency::builder()
.src(&*self.instance())
.build(),
);
}
}
@ -1453,11 +1431,13 @@ impl ElementImpl for FallbackSwitch {
//
// This allows accessing the pads and their properties from e.g. gst-launch.
impl ChildProxyImpl for FallbackSwitch {
fn children_count(&self, object: &Self::Type) -> u32 {
fn children_count(&self) -> u32 {
let object = self.instance();
object.num_pads() as u32
}
fn child_by_name(&self, object: &Self::Type, name: &str) -> Option<glib::Object> {
fn child_by_name(&self, name: &str) -> Option<glib::Object> {
let object = self.instance();
object
.pads()
.into_iter()
@ -1465,7 +1445,8 @@ impl ChildProxyImpl for FallbackSwitch {
.map(|p| p.upcast())
}
fn child_by_index(&self, object: &Self::Type, index: u32) -> Option<glib::Object> {
fn child_by_index(&self, index: u32) -> Option<glib::Object> {
let object = self.instance();
object
.pads()
.into_iter()

View file

@ -331,7 +331,6 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
impl ToggleRecord {
fn handle_main_stream<T: HandleData>(
&self,
element: &super::ToggleRecord,
pad: &gst::Pad,
stream: &Stream,
data: T,
@ -339,8 +338,8 @@ impl ToggleRecord {
let mut state = stream.state.lock();
let mut dts_or_pts = data.dts_or_pts().ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Buffer without DTS or PTS"]
);
@ -498,7 +497,7 @@ impl ToggleRecord {
drop(rec_state);
drop(state);
element.notify("recording");
self.instance().notify("recording");
Ok(HandleResult::Drop)
}
@ -584,7 +583,7 @@ impl ToggleRecord {
drop(rec_state);
drop(state);
element.notify("recording");
self.instance().notify("recording");
Ok(HandleResult::Pass(data))
}
@ -594,7 +593,6 @@ impl ToggleRecord {
#[allow(clippy::blocks_in_if_conditions)]
fn handle_secondary_stream<T: HandleData>(
&self,
element: &super::ToggleRecord,
pad: &gst::Pad,
stream: &Stream,
data: T,
@ -603,13 +601,13 @@ impl ToggleRecord {
let mut state = stream.state.lock();
let mut pts = data.pts().ok_or_else(|| {
gst::element_error!(element, gst::StreamError::Format, ["Buffer without PTS"]);
gst::element_imp_error!(self, gst::StreamError::Format, ["Buffer without PTS"]);
gst::FlowError::Error
})?;
if data.dts().map_or(false, |dts| dts != pts) {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["DTS != PTS not supported for secondary streams"]
);
@ -617,8 +615,8 @@ impl ToggleRecord {
}
if !data.is_keyframe() {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Delta-units not supported for secondary streams"]
);
@ -1149,15 +1147,10 @@ impl ToggleRecord {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::ToggleRecord,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let stream = self.pads.lock().get(pad).cloned().ok_or_else(|| {
gst::element_error!(
element,
gst::CoreError::Pad,
["Unknown pad {:?}", pad.name()]
);
gst::element_imp_error!(self, gst::CoreError::Pad, ["Unknown pad {:?}", pad.name()]);
gst::FlowError::Error
})?;
@ -1174,9 +1167,9 @@ impl ToggleRecord {
}
let handle_result = if stream != self.main_stream {
self.handle_secondary_stream(element, pad, &stream, buffer)
self.handle_secondary_stream(pad, &stream, buffer)
} else {
self.handle_main_stream(element, pad, &stream, buffer)
self.handle_main_stream(pad, &stream, buffer)
}?;
let mut buffer = match handle_result {
@ -1194,7 +1187,7 @@ impl ToggleRecord {
);
if recording_state_updated {
element.notify("recording");
self.instance().notify("recording");
}
return Err(gst::FlowError::Eos);
@ -1275,18 +1268,13 @@ impl ToggleRecord {
stream.srcpad.push(buffer)
}
fn sink_event(
&self,
pad: &gst::Pad,
element: &super::ToggleRecord,
mut event: gst::Event,
) -> bool {
fn sink_event(&self, pad: &gst::Pad, mut event: gst::Event) -> bool {
use gst::EventView;
let stream = match self.pads.lock().get(pad) {
None => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Pad,
["Unknown pad {:?}", pad.name()]
);
@ -1345,8 +1333,8 @@ impl ToggleRecord {
let segment = match e.segment().clone().downcast::<gst::ClockTime>() {
Err(segment) => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Only Time segments supported, got {:?}", segment.format(),]
);
@ -1356,8 +1344,8 @@ impl ToggleRecord {
};
if (segment.rate() - 1.0).abs() > f64::EPSILON {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
[
"Only rate==1.0 segments supported, got {:?}",
@ -1381,9 +1369,9 @@ impl ToggleRecord {
gst::debug!(CAT, obj: pad, "Handling Gap event {:?}", event);
let (pts, duration) = e.get();
let handle_result = if stream == self.main_stream {
self.handle_main_stream(element, pad, &stream, (pts, duration))
self.handle_main_stream(pad, &stream, (pts, duration))
} else {
self.handle_secondary_stream(element, pad, &stream, (pts, duration))
self.handle_secondary_stream(pad, &stream, (pts, duration))
};
forward = match handle_result {
@ -1456,7 +1444,7 @@ impl ToggleRecord {
};
if recording_state_changed {
element.notify("recording");
self.instance().notify("recording");
}
// If a serialized event and coming after Segment and a new Segment is pending,
@ -1505,16 +1493,11 @@ impl ToggleRecord {
}
}
fn sink_query(
&self,
pad: &gst::Pad,
element: &super::ToggleRecord,
query: &mut gst::QueryRef,
) -> bool {
fn sink_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
let stream = match self.pads.lock().get(pad) {
None => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Pad,
["Unknown pad {:?}", pad.name()]
);
@ -1531,18 +1514,13 @@ impl ToggleRecord {
// FIXME `matches!` was introduced in rustc 1.42.0, current MSRV is 1.41.0
// FIXME uncomment when CI can upgrade to 1.47.1
//#[allow(clippy::match_like_matches_macro)]
fn src_event(
&self,
pad: &gst::Pad,
element: &super::ToggleRecord,
mut event: gst::Event,
) -> bool {
fn src_event(&self, pad: &gst::Pad, mut event: gst::Event) -> bool {
use gst::EventView;
let stream = match self.pads.lock().get(pad) {
None => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Pad,
["Unknown pad {:?}", pad.name()]
);
@ -1571,18 +1549,13 @@ impl ToggleRecord {
}
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::ToggleRecord,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
let stream = match self.pads.lock().get(pad) {
None => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Pad,
["Unknown pad {:?}", pad.name()]
);
@ -1703,15 +1676,11 @@ impl ToggleRecord {
}
}
fn iterate_internal_links(
&self,
pad: &gst::Pad,
element: &super::ToggleRecord,
) -> gst::Iterator<gst::Pad> {
fn iterate_internal_links(&self, pad: &gst::Pad) -> gst::Iterator<gst::Pad> {
let stream = match self.pads.lock().get(pad) {
None => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Pad,
["Unknown pad {:?}", pad.name()]
);
@ -1741,28 +1710,28 @@ impl ObjectSubclass for ToggleRecord {
ToggleRecord::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|togglerecord, element| togglerecord.sink_chain(pad, element, buffer),
|togglerecord| togglerecord.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.sink_event(pad, element, event),
|togglerecord| togglerecord.sink_event(pad, event),
)
})
.query_function(|pad, parent, query| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.sink_query(pad, element, query),
|togglerecord| togglerecord.sink_query(pad, query),
)
})
.iterate_internal_links_function(|pad, parent| {
ToggleRecord::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|togglerecord, element| togglerecord.iterate_internal_links(pad, element),
|togglerecord| togglerecord.iterate_internal_links(pad),
)
})
.build();
@ -1773,21 +1742,21 @@ impl ObjectSubclass for ToggleRecord {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.src_event(pad, element, event),
|togglerecord| togglerecord.src_event(pad, event),
)
})
.query_function(|pad, parent, query| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.src_query(pad, element, query),
|togglerecord| togglerecord.src_query(pad, query),
)
})
.iterate_internal_links_function(|pad, parent| {
ToggleRecord::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|togglerecord, element| togglerecord.iterate_internal_links(pad, element),
|togglerecord| togglerecord.iterate_internal_links(pad),
)
})
.build();
@ -1837,20 +1806,14 @@ impl ObjectImpl for ToggleRecord {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"record" => {
let mut settings = self.settings.lock();
let record = value.get().expect("type checked upstream");
gst::debug!(
CAT,
obj: obj,
imp: self,
"Setting record from {:?} to {:?}",
settings.record,
record
@ -1863,7 +1826,7 @@ impl ObjectImpl for ToggleRecord {
let live = value.get().expect("type checked upstream");
gst::debug!(
CAT,
obj: obj,
imp: self,
"Setting live from {:?} to {:?}",
settings.live,
live
@ -1875,7 +1838,7 @@ impl ObjectImpl for ToggleRecord {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"record" => {
let settings = self.settings.lock();
@ -1893,9 +1856,10 @@ impl ObjectImpl for ToggleRecord {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.main_stream.sinkpad).unwrap();
obj.add_pad(&self.main_stream.srcpad).unwrap();
}
@ -1965,10 +1929,9 @@ impl ElementImpl for ToggleRecord {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused => {
@ -2001,7 +1964,7 @@ impl ElementImpl for ToggleRecord {
_ => (),
}
let success = self.parent_change_state(element, transition)?;
let success = self.parent_change_state(transition)?;
if transition == gst::StateChange::PausedToReady {
for s in self
@ -2019,7 +1982,7 @@ impl ElementImpl for ToggleRecord {
let mut rec_state = self.state.lock();
*rec_state = State::default();
drop(rec_state);
element.notify("recording");
self.instance().notify("recording");
}
Ok(success)
@ -2027,7 +1990,6 @@ impl ElementImpl for ToggleRecord {
fn request_new_pad(
&self,
element: &Self::Type,
_templ: &gst::PadTemplate,
_name: Option<String>,
_caps: Option<&gst::Caps>,
@ -2039,60 +2001,60 @@ impl ElementImpl for ToggleRecord {
let id = *pad_count;
*pad_count += 1;
let templ = element.pad_template("sink_%u").unwrap();
let templ = self.instance().pad_template("sink_%u").unwrap();
let sinkpad =
gst::Pad::builder_with_template(&templ, Some(format!("sink_{}", id).as_str()))
.chain_function(|pad, parent, buffer| {
ToggleRecord::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|togglerecord, element| togglerecord.sink_chain(pad, element, buffer),
|togglerecord| togglerecord.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.sink_event(pad, element, event),
|togglerecord| togglerecord.sink_event(pad, event),
)
})
.query_function(|pad, parent, query| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.sink_query(pad, element, query),
|togglerecord| togglerecord.sink_query(pad, query),
)
})
.iterate_internal_links_function(|pad, parent| {
ToggleRecord::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|togglerecord, element| togglerecord.iterate_internal_links(pad, element),
|togglerecord| togglerecord.iterate_internal_links(pad),
)
})
.build();
let templ = element.pad_template("src_%u").unwrap();
let templ = self.instance().pad_template("src_%u").unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some(format!("src_{}", id).as_str()))
.event_function(|pad, parent, event| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.src_event(pad, element, event),
|togglerecord| togglerecord.src_event(pad, event),
)
})
.query_function(|pad, parent, query| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.src_query(pad, element, query),
|togglerecord| togglerecord.src_query(pad, query),
)
})
.iterate_internal_links_function(|pad, parent| {
ToggleRecord::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|togglerecord, element| togglerecord.iterate_internal_links(pad, element),
|togglerecord| togglerecord.iterate_internal_links(pad),
)
})
.build();
@ -2110,13 +2072,13 @@ impl ElementImpl for ToggleRecord {
drop(pads);
drop(other_streams_guard);
element.add_pad(&sinkpad).unwrap();
element.add_pad(&srcpad).unwrap();
self.instance().add_pad(&sinkpad).unwrap();
self.instance().add_pad(&srcpad).unwrap();
Some(sinkpad)
}
fn release_pad(&self, element: &Self::Type, pad: &gst::Pad) {
fn release_pad(&self, pad: &gst::Pad) {
let mut other_streams_guard = self.other_streams.lock();
let (ref mut other_streams, _) = *other_streams_guard;
let mut pads = self.pads.lock();
@ -2143,7 +2105,7 @@ impl ElementImpl for ToggleRecord {
stream.srcpad.set_active(false).unwrap();
stream.sinkpad.set_active(false).unwrap();
element.remove_pad(&stream.sinkpad).unwrap();
element.remove_pad(&stream.srcpad).unwrap();
self.instance().remove_pad(&stream.sinkpad).unwrap();
self.instance().remove_pad(&stream.srcpad).unwrap();
}
}

View file

@ -84,28 +84,28 @@ impl Default for Settings {
}
impl Settings {
fn update_from_params(&mut self, obj: &super::BufferLateness, params: String) {
fn update_from_params(&mut self, imp: &BufferLateness, params: String) {
let s = match gst::Structure::from_str(&format!("buffer-lateness,{}", params)) {
Ok(s) => s,
Err(err) => {
gst::warning!(CAT, obj: obj, "failed to parse tracer parameters: {}", err);
gst::warning!(CAT, imp: imp, "failed to parse tracer parameters: {}", err);
return;
}
};
if let Ok(file) = s.get::<&str>("file") {
gst::log!(CAT, obj: obj, "file= {}", file);
gst::log!(CAT, imp: imp, "file= {}", file);
self.file = PathBuf::from(file);
}
if let Ok(filter) = s.get::<&str>("include-filter") {
gst::log!(CAT, obj: obj, "include filter= {}", filter);
gst::log!(CAT, imp: imp, "include filter= {}", filter);
let filter = match Regex::new(filter) {
Ok(filter) => Some(filter),
Err(err) => {
gst::error!(
CAT,
obj: obj,
imp: imp,
"Failed to compile include-filter regex: {}",
err
);
@ -116,13 +116,13 @@ impl Settings {
}
if let Ok(filter) = s.get::<&str>("exclude-filter") {
gst::log!(CAT, obj: obj, "exclude filter= {}", filter);
gst::log!(CAT, imp: imp, "exclude filter= {}", filter);
let filter = match Regex::new(filter) {
Ok(filter) => Some(filter),
Err(err) => {
gst::error!(
CAT,
obj: obj,
imp: imp,
"Failed to compile exclude-filter regex: {}",
err
);
@ -171,12 +171,12 @@ impl ObjectSubclass for BufferLateness {
}
impl ObjectImpl for BufferLateness {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
if let Some(params) = obj.property::<Option<String>>("params") {
if let Some(params) = self.instance().property::<Option<String>>("params") {
let mut state = self.state.lock().unwrap();
state.settings.update_from_params(obj, params);
state.settings.update_from_params(self, params);
}
self.register_hook(TracerHook::ElementAddPad);
@ -186,7 +186,7 @@ impl ObjectImpl for BufferLateness {
self.register_hook(TracerHook::PadQueryPost);
}
fn dispose(&self, obj: &Self::Type) {
fn dispose(&self) {
use std::io::prelude::*;
let state = self.state.lock().unwrap();
@ -194,14 +194,14 @@ impl ObjectImpl for BufferLateness {
let mut file = match std::fs::File::create(&state.settings.file) {
Ok(file) => file,
Err(err) => {
gst::error!(CAT, obj: obj, "Failed to create file: {err}");
gst::error!(CAT, imp: self, "Failed to create file: {err}");
return;
}
};
gst::debug!(
CAT,
obj: obj,
imp: self,
"Writing file {}",
state.settings.file.display()
);
@ -218,7 +218,7 @@ impl ObjectImpl for BufferLateness {
} in &state.log
{
if let Err(err) = writeln!(&mut file, "{timestamp},{element_name}:{pad_name},0x{ptr:08x},{buffer_clock_time},{pipeline_clock_time},{lateness},{min_latency}") {
gst::error!(CAT, obj: obj, "Failed to write to file: {err}");
gst::error!(CAT, imp: self, "Failed to write to file: {err}");
return;
}
}
@ -233,11 +233,10 @@ impl TracerImpl for BufferLateness {
return;
}
let tracer = self.instance();
let ptr = pad.as_ptr() as usize;
gst::debug!(
CAT,
obj: &tracer,
imp: self,
"new source pad: {} 0x{:08x}",
pad.name(),
ptr

View file

@ -89,22 +89,22 @@ impl Default for Settings {
}
impl Settings {
fn update_from_params(&mut self, obj: &super::PipelineSnapshot, params: String) {
fn update_from_params(&mut self, imp: &PipelineSnapshot, params: String) {
let s = match gst::Structure::from_str(&format!("pipeline-snapshot,{}", params)) {
Ok(s) => s,
Err(err) => {
gst::warning!(CAT, obj: obj, "failed to parse tracer parameters: {}", err);
gst::warning!(CAT, imp: imp, "failed to parse tracer parameters: {}", err);
return;
}
};
if let Ok(dot_prefix) = s.get("dot-prefix") {
gst::log!(CAT, obj: obj, "dot-prefix = {}", dot_prefix);
gst::log!(CAT, imp: imp, "dot-prefix = {}", dot_prefix);
self.dot_prefix = dot_prefix;
}
if let Ok(dot_ts) = s.get("dot-ts") {
gst::log!(CAT, obj: obj, "dot-ts = {}", dot_ts);
gst::log!(CAT, imp: imp, "dot-ts = {}", dot_ts);
self.dot_ts = dot_ts;
}
}
@ -130,23 +130,23 @@ impl ObjectSubclass for PipelineSnapshot {
}
impl ObjectImpl for PipelineSnapshot {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let mut settings = Settings::default();
if let Some(params) = obj.property::<Option<String>>("params") {
settings.update_from_params(obj, params);
if let Some(params) = self.instance().property::<Option<String>>("params") {
settings.update_from_params(self, params);
}
self.register_hook(TracerHook::ElementNew);
self.register_hook(TracerHook::ObjectDestroyed);
if let Err(err) = self.setup_signal(settings) {
gst::warning!(CAT, obj: obj, "failed to setup UNIX signals: {}", err);
gst::warning!(CAT, imp: self, "failed to setup UNIX signals: {}", err);
}
}
fn dispose(&self, _obj: &Self::Type) {
fn dispose(&self) {
let mut handles = self.handles.lock().unwrap();
if let Some(handles) = handles.take() {
#[cfg(unix)]
@ -161,8 +161,7 @@ impl GstObjectImpl for PipelineSnapshot {}
impl TracerImpl for PipelineSnapshot {
fn element_new(&self, _ts: u64, element: &gst::Element) {
if element.is::<gst::Pipeline>() {
let tracer = self.instance();
gst::debug!(CAT, obj: &tracer, "new pipeline: {}", element.name());
gst::debug!(CAT, imp: self, "new pipeline: {}", element.name());
let weak = element.downgrade();
let mut pipelines = self.pipelines.lock().unwrap();

View file

@ -115,28 +115,28 @@ impl Default for Settings {
}
impl Settings {
fn update_from_params(&mut self, obj: &super::QueueLevels, params: String) {
fn update_from_params(&mut self, imp: &QueueLevels, params: String) {
let s = match gst::Structure::from_str(&format!("queue-levels,{}", params)) {
Ok(s) => s,
Err(err) => {
gst::warning!(CAT, obj: obj, "failed to parse tracer parameters: {}", err);
gst::warning!(CAT, imp: imp, "failed to parse tracer parameters: {}", err);
return;
}
};
if let Ok(file) = s.get::<&str>("file") {
gst::log!(CAT, obj: obj, "file= {}", file);
gst::log!(CAT, imp: imp, "file= {}", file);
self.file = PathBuf::from(file);
}
if let Ok(filter) = s.get::<&str>("include-filter") {
gst::log!(CAT, obj: obj, "include filter= {}", filter);
gst::log!(CAT, imp: imp, "include filter= {}", filter);
let filter = match Regex::new(filter) {
Ok(filter) => Some(filter),
Err(err) => {
gst::error!(
CAT,
obj: obj,
imp: imp,
"Failed to compile include-filter regex: {}",
err
);
@ -147,13 +147,13 @@ impl Settings {
}
if let Ok(filter) = s.get::<&str>("exclude-filter") {
gst::log!(CAT, obj: obj, "exclude filter= {}", filter);
gst::log!(CAT, imp: imp, "exclude filter= {}", filter);
let filter = match Regex::new(filter) {
Ok(filter) => Some(filter),
Err(err) => {
gst::error!(
CAT,
obj: obj,
imp: imp,
"Failed to compile exclude-filter regex: {}",
err
);
@ -198,12 +198,12 @@ impl ObjectSubclass for QueueLevels {
}
impl ObjectImpl for QueueLevels {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
if let Some(params) = obj.property::<Option<String>>("params") {
if let Some(params) = self.instance().property::<Option<String>>("params") {
let mut state = self.state.lock().unwrap();
state.settings.update_from_params(obj, params);
state.settings.update_from_params(self, params);
}
Lazy::force(&QUEUE_TYPE);
@ -230,7 +230,7 @@ impl ObjectImpl for QueueLevels {
self.register_hook(TracerHook::PadPushEventPre);
}
fn dispose(&self, obj: &Self::Type) {
fn dispose(&self) {
use std::io::prelude::*;
let state = self.state.lock().unwrap();
@ -238,14 +238,14 @@ impl ObjectImpl for QueueLevels {
let mut file = match std::fs::File::create(&state.settings.file) {
Ok(file) => file,
Err(err) => {
gst::error!(CAT, obj: obj, "Failed to create file: {err}");
gst::error!(CAT, imp: self, "Failed to create file: {err}");
return;
}
};
gst::debug!(
CAT,
obj: obj,
imp: self,
"Writing file {}",
state.settings.file.display()
);
@ -269,7 +269,7 @@ impl ObjectImpl for QueueLevels {
writeln!(&mut file, "{timestamp},{name},0x{ptr:08x},{cur_level_bytes},{cur_level_time},{cur_level_buffers},{max_size_bytes},{max_size_time},{max_size_buffers}")
};
if let Err(err) = res {
gst::error!(CAT, obj: obj, "Failed to write to file: {err}");
gst::error!(CAT, imp: self, "Failed to write to file: {err}");
return;
}
}
@ -284,11 +284,10 @@ impl TracerImpl for QueueLevels {
return;
}
let tracer = self.instance();
let ptr = element.as_ptr() as usize;
gst::debug!(
CAT,
obj: &tracer,
imp: self,
"new queue: {} 0x{:08x}",
element.name(),
ptr

View file

@ -192,20 +192,20 @@ impl State {
.cloned()
}
fn unblock_item(&mut self, element: &super::UriPlaylistBin) {
fn unblock_item(&mut self, imp: &UriPlaylistBin) {
if let Some(blocked) = self.blocked.take() {
let (messages, channels) = blocked.set_streaming(self.streams_topology.n_streams());
gst::log!(
CAT,
obj: element,
imp: imp,
"send pending message of item #{} and unblock its pads",
blocked.index()
);
// send pending messages then unblock pads
for msg in messages {
let _ = element.post_message(msg);
let _ = imp.instance().post_message(msg);
}
channels.send(true);
@ -764,20 +764,14 @@ impl ObjectImpl for UriPlaylistBin {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"uris" => {
let mut settings = self.settings.lock().unwrap();
let new_value = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing uris from {:?} to {:?}",
settings.uris,
new_value,
@ -789,7 +783,7 @@ impl ObjectImpl for UriPlaylistBin {
let new_value = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing iterations from {:?} to {:?}",
settings.iterations,
new_value,
@ -800,7 +794,7 @@ impl ObjectImpl for UriPlaylistBin {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"uris" => {
let settings = self.settings.lock().unwrap();
@ -830,9 +824,10 @@ impl ObjectImpl for UriPlaylistBin {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.set_suppressed_flags(gst::ElementFlags::SOURCE | gst::ElementFlags::SINK);
obj.set_element_flags(gst::ElementFlags::SOURCE);
}
@ -841,24 +836,23 @@ impl ObjectImpl for UriPlaylistBin {
impl GstObjectImpl for UriPlaylistBin {}
impl BinImpl for UriPlaylistBin {
fn handle_message(&self, element: &Self::Type, msg: gst::Message) {
fn handle_message(&self, msg: gst::Message) {
match msg.view() {
gst::MessageView::StreamCollection(stream_collection_msg) => {
if let Err(e) = self.handle_stream_collection(element, stream_collection_msg) {
self.failed(element, e);
if let Err(e) = self.handle_stream_collection(stream_collection_msg) {
self.failed(e);
}
// stream collection will be send when the item starts streaming
return;
}
gst::MessageView::StreamsSelected(stream_selected) => {
if !self.handle_stream_selected(element, stream_selected) {
if !self.handle_stream_selected(stream_selected) {
return;
}
}
gst::MessageView::Error(error) => {
// find item which raised the error
let imp = element.imp();
let mut state_guard = imp.state.lock().unwrap();
let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().unwrap();
let src = error.src().unwrap();
@ -869,25 +863,22 @@ impl BinImpl for UriPlaylistBin {
if let Some(item) = item {
// handle the error message so we can add the failing uri as error details
self.failed(
element,
PlaylistError::ItemFailed {
error: anyhow::anyhow!(
"Error when processing item #{} ({}): {}",
item.index(),
item.uri(),
error.error().to_string()
),
item,
},
);
self.failed(PlaylistError::ItemFailed {
error: anyhow::anyhow!(
"Error when processing item #{} ({}): {}",
item.index(),
item.uri(),
error.error().to_string()
),
item,
});
return;
}
}
_ => (),
}
self.parent_handle_message(element, msg)
self.parent_handle_message(msg)
}
}
@ -943,12 +934,11 @@ impl ElementImpl for UriPlaylistBin {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
if transition == gst::StateChange::NullToReady {
if let Err(e) = self.start(element) {
self.failed(element, e);
if let Err(e) = self.start() {
self.failed(e);
return Err(gst::StateChangeError);
}
}
@ -973,13 +963,13 @@ impl ElementImpl for UriPlaylistBin {
}
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}
impl UriPlaylistBin {
fn start(&self, element: &super::UriPlaylistBin) -> Result<(), PlaylistError> {
gst::debug!(CAT, obj: element, "Starting");
fn start(&self) -> Result<(), PlaylistError> {
gst::debug!(CAT, imp: self, "Starting");
{
let mut state_guard = self.state.lock().unwrap();
assert!(state_guard.is_none());
@ -988,7 +978,7 @@ impl UriPlaylistBin {
gst::ElementFactory::make("streamsynchronizer", Some("playlist-streamsync"))
.map_err(|e| PlaylistError::PluginMissing { error: e.into() })?;
element.add(&streamsynchronizer).unwrap();
self.instance().add(&streamsynchronizer).unwrap();
let settings = self.settings.lock().unwrap();
@ -999,19 +989,19 @@ impl UriPlaylistBin {
));
}
self.start_next_item(element)?;
self.start_next_item()?;
Ok(())
}
fn start_next_item(&self, element: &super::UriPlaylistBin) -> Result<(), PlaylistError> {
fn start_next_item(&self) -> Result<(), PlaylistError> {
let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().unwrap();
// clean up done items, so uridecodebin elements and concat sink pads don't pile up in the pipeline
while let Some(done) = state.done.pop() {
let uridecodebin = done.uridecodebin();
gst::log!(CAT, obj: element, "remove {} from bin", uridecodebin.name());
gst::log!(CAT, imp: self, "remove {} from bin", uridecodebin.name());
for (concat, sink_pad) in done.concat_sink_pads() {
// calling release_request_pad() while holding the pad stream lock would deadlock
@ -1021,12 +1011,11 @@ impl UriPlaylistBin {
}
// can't change state from the streaming thread
let uridecodebin_clone = uridecodebin.clone();
element.call_async(move |_element| {
let _ = uridecodebin_clone.set_state(gst::State::Null);
uridecodebin.call_async(move |uridecodebin| {
let _ = uridecodebin.set_state(gst::State::Null);
});
element.remove(&uridecodebin).unwrap();
self.instance().remove(&uridecodebin).unwrap();
}
if state.waiting_for_stream_collection.is_some()
@ -1041,7 +1030,7 @@ impl UriPlaylistBin {
if n_streaming >= MAX_STREAMING_ITEMS {
gst::log!(
CAT,
obj: element,
imp: self,
"Too many items streaming ({}), wait before starting the next one",
n_streaming
);
@ -1052,10 +1041,10 @@ impl UriPlaylistBin {
let item = match state.playlist.next()? {
Some(item) => item,
None => {
gst::debug!(CAT, obj: element, "no more item to queue",);
gst::debug!(CAT, imp: self, "no more item to queue",);
// unblock last item
state.unblock_item(element);
state.unblock_item(self);
self.update_current(state_guard);
@ -1065,7 +1054,7 @@ impl UriPlaylistBin {
gst::debug!(
CAT,
obj: element,
imp: self,
"start decoding item #{}: {}",
item.index(),
item.uri()
@ -1073,16 +1062,17 @@ impl UriPlaylistBin {
let uridecodebin = item.uridecodebin();
element.add(&uridecodebin).unwrap();
let element_weak = element.downgrade();
self.instance().add(&uridecodebin).unwrap();
let item_clone = item.clone();
assert!(state.waiting_for_stream_collection.is_none());
state.waiting_for_stream_collection = Some(item);
uridecodebin.connect_pad_added(move |_uridecodebin, src_pad| {
let element = match element_weak.upgrade() {
uridecodebin.connect_pad_added(move |uridecodebin, src_pad| {
let element = match uridecodebin
.parent()
.and_then(|p| p.downcast::<super::UriPlaylistBin>().ok())
{
Some(element) => element,
None => return,
};
@ -1092,33 +1082,34 @@ impl UriPlaylistBin {
if let Some(item) = state.waiting_for_ss_eos.as_ref() {
// block pad until streamsynchronizer is eos
let element_weak = element.downgrade();
let imp_weak = imp.downgrade();
let receiver = Mutex::new(item.receiver());
gst::debug!(
CAT,
obj: &element,
imp: imp,
"Block pad {} until streamsynchronizer is flushed",
src_pad.name(),
);
src_pad.add_probe(gst::PadProbeType::BLOCK_DOWNSTREAM, move |pad, _info| {
let element = match element_weak.upgrade() {
Some(element) => element,
let imp = match imp_weak.upgrade() {
Some(imp) => imp,
None => return gst::PadProbeReturn::Remove,
};
let parent = pad.parent().unwrap();
let receiver = receiver.lock().unwrap();
let _ = receiver.recv();
if let Some(parent) = pad.parent() {
let receiver = receiver.lock().unwrap();
let _ = receiver.recv();
gst::log!(
CAT,
obj: &element,
"pad {}:{} has been unblocked",
parent.name(),
pad.name()
);
gst::log!(
CAT,
imp: imp,
"pad {}:{} has been unblocked",
parent.name(),
pad.name()
);
}
gst::PadProbeReturn::Remove
});
@ -1144,7 +1135,6 @@ impl UriPlaylistBin {
fn handle_stream_collection(
&self,
element: &super::UriPlaylistBin,
stream_collection_msg: &gst::message::StreamCollection,
) -> Result<(), PlaylistError> {
let mut state_guard = self.state.lock().unwrap();
@ -1160,7 +1150,7 @@ impl UriPlaylistBin {
gst::debug!(
CAT,
obj: element,
imp: self,
"got stream collection from {}: {:?}",
src.name(),
topology
@ -1175,7 +1165,7 @@ impl UriPlaylistBin {
if state.streams_topology != topology {
gst::debug!(
CAT,
obj: element, "streams topoly changed ('{:?}' -> '{:?}'), waiting for streamsynchronize to be flushed",
imp: self, "streams topoly changed ('{:?}' -> '{:?}'), waiting for streamsynchronize to be flushed",
state.streams_topology, topology);
item.set_waiting_for_ss_eos(
state.streams_topology.n_streams(),
@ -1184,7 +1174,7 @@ impl UriPlaylistBin {
state.waiting_for_ss_eos = Some(item);
// unblock previous item as we need it to be flushed out of streamsynchronizer
state.unblock_item(element);
state.unblock_item(self);
} else {
item.set_waiting_for_pads(topology.n_streams(), stream_collection_msg);
state.waiting_for_pads = Some(item);
@ -1199,11 +1189,7 @@ impl UriPlaylistBin {
}
// return true if the message can be forwarded
fn handle_stream_selected(
&self,
element: &super::UriPlaylistBin,
stream_selected_msg: &gst::message::StreamsSelected,
) -> bool {
fn handle_stream_selected(&self, stream_selected_msg: &gst::message::StreamsSelected) -> bool {
let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().unwrap();
let src = stream_selected_msg.src().unwrap();
@ -1215,7 +1201,7 @@ impl UriPlaylistBin {
// stream-selected message is from the blocked item, queue the message until it's unblocked
gst::debug!(
CAT,
obj: element,
imp: self,
"queue stream-selected message from {} as item is currently blocked",
src.name(),
);
@ -1253,7 +1239,7 @@ impl UriPlaylistBin {
let (stream_type, stream_index) = match stream_type_from_pad_name(&pad_name) {
Ok((stream_type, stream_index)) => (stream_type, stream_index),
Err(e) => {
gst::warning!(CAT, obj: &element, "Ignoring pad {}: {}", pad_name, e);
gst::warning!(CAT, imp: self, "Ignoring pad {}: {}", pad_name, e);
return;
}
};
@ -1269,7 +1255,7 @@ impl UriPlaylistBin {
None => {
gst::debug!(
CAT,
obj: &element,
imp: self,
"stream {} from item #{}: creating concat element",
pad_name,
item.index()
@ -1286,12 +1272,9 @@ impl UriPlaylistBin {
Ok(concat) => concat,
Err(_) => {
drop(state_guard);
self.failed(
&element,
PlaylistError::PluginMissing {
error: anyhow::anyhow!("element 'concat' missing"),
},
);
self.failed(PlaylistError::PluginMissing {
error: anyhow::anyhow!("element 'concat' missing"),
});
return;
}
};
@ -1336,8 +1319,8 @@ impl UriPlaylistBin {
if let Some(item) = item {
if item.dec_waiting_eos_ss() {
gst::debug!(CAT, obj: &element, "streamsynchronizer has been flushed, reorganize pipeline to fit new streams topology and unblock item");
imp.handle_topology_change(&element);
gst::debug!(CAT, imp: imp, "streamsynchronizer has been flushed, reorganize pipeline to fit new streams topology and unblock item");
imp.handle_topology_change();
gst::PadProbeReturn::Drop
} else {
gst::PadProbeReturn::Drop
@ -1367,13 +1350,14 @@ impl UriPlaylistBin {
ghost.set_event_function(|pad, parent, event| match event.view() {
gst::EventView::SelectStreams(_) => {
// TODO: handle select-streams event
let element = parent.unwrap();
gst::fixme!(
CAT,
obj: element,
"select-streams event not supported ('{:?}')",
event
);
if let Some(element) = parent {
gst::fixme!(
CAT,
obj: element,
"select-streams event not supported ('{:?}')",
event
);
}
false
}
_ => pad.event_default(parent, event),
@ -1400,7 +1384,7 @@ impl UriPlaylistBin {
Some(concat) => {
gst::debug!(
CAT,
obj: &element,
imp: self,
"stream {} from item #{}: re-using concat element {}",
pad_name,
item.index(),
@ -1494,8 +1478,8 @@ impl UriPlaylistBin {
}
}
if let Err(e) = imp.start_next_item(&element) {
imp.failed(&element, e);
if let Err(e) = imp.start_next_item() {
imp.failed(e);
}
}
@ -1510,13 +1494,13 @@ impl UriPlaylistBin {
// we got all the pads
gst::debug!(
CAT,
obj: &element,
imp: self,
"got all the pads for item #{}",
item.index()
);
// all pads have been linked to concat, unblock previous item
state.unblock_item(&element);
state.unblock_item(self);
state.waiting_for_pads = None;
// block item until the next one is fully linked to concat
@ -1532,14 +1516,10 @@ impl UriPlaylistBin {
};
if start_next {
gst::debug!(
CAT,
obj: &element,
"got all pending streams, queue next item"
);
gst::debug!(CAT, imp: self, "got all pending streams, queue next item");
if let Err(e) = self.start_next_item(&element) {
self.failed(&element, e);
if let Err(e) = self.start_next_item() {
self.failed(e);
}
}
}
@ -1547,7 +1527,7 @@ impl UriPlaylistBin {
/// called when all previous items have been flushed from streamsynchronizer
/// and so the elements can reorganize itself to handle a pending changes in
/// streams topology.
fn handle_topology_change(&self, element: &super::UriPlaylistBin) {
fn handle_topology_change(&self) {
let (pending_pads, channels) = {
let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().unwrap();
@ -1563,15 +1543,15 @@ impl UriPlaylistBin {
// remove now useless concat elements, missing ones will be added when handling src pads from decodebin
fn remove_useless_concat(
imp: &UriPlaylistBin,
n_stream: usize,
concats: &mut Vec<gst::Element>,
element: &super::UriPlaylistBin,
streamsynchronizer: &gst::Element,
) {
while n_stream < concats.len() {
// need to remove concat elements
let concat = concats.pop().unwrap();
gst::log!(CAT, obj: element, "remove {}", concat.name());
gst::log!(CAT, imp: imp, "remove {}", concat.name());
let concat_src = concat.static_pad("src").unwrap();
let ss_sink = concat_src.peer().unwrap();
@ -1581,7 +1561,7 @@ impl UriPlaylistBin {
streamsynchronizer.release_request_pad(&ss_sink);
// remove associated ghost pad
let src_pads = element.src_pads();
let src_pads = imp.instance().src_pads();
let ghost = src_pads
.iter()
.find(|pad| {
@ -1589,29 +1569,29 @@ impl UriPlaylistBin {
ghost.target().is_none()
})
.unwrap();
element.remove_pad(ghost).unwrap();
imp.instance().remove_pad(ghost).unwrap();
element.remove(&concat).unwrap();
imp.instance().remove(&concat).unwrap();
let _ = concat.set_state(gst::State::Null);
}
}
remove_useless_concat(
self,
topology.audio as usize,
&mut state.concat_audio,
element,
&state.streamsynchronizer,
);
remove_useless_concat(
self,
topology.video as usize,
&mut state.concat_video,
element,
&state.streamsynchronizer,
);
remove_useless_concat(
self,
topology.text as usize,
&mut state.concat_text,
element,
&state.streamsynchronizer,
);
@ -1628,7 +1608,7 @@ impl UriPlaylistBin {
channels.send(true);
}
fn failed(&self, element: &super::UriPlaylistBin, error: PlaylistError) {
fn failed(&self, error: PlaylistError) {
{
let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().unwrap();
@ -1644,11 +1624,11 @@ impl UriPlaylistBin {
}
}
let error_msg = error.to_string();
gst::error!(CAT, obj: element, "{}", error_msg);
gst::error!(CAT, imp: self, "{}", error_msg);
match error {
PlaylistError::PluginMissing { .. } => {
gst::element_error!(element, gst::CoreError::MissingPlugin, [&error_msg]);
gst::element_imp_error!(self, gst::CoreError::MissingPlugin, [&error_msg]);
}
PlaylistError::ItemFailed { item, .. } => {
// remove failing uridecodebin
@ -1656,13 +1636,13 @@ impl UriPlaylistBin {
uridecodebin.call_async(move |uridecodebin| {
let _ = uridecodebin.set_state(gst::State::Null);
});
let _ = element.remove(&uridecodebin);
let _ = self.instance().remove(&uridecodebin);
let details = gst::Structure::builder("details");
let details = details.field("uri", item.uri());
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::LibraryError::Failed,
[&error_msg],
details: details.build()
@ -1693,7 +1673,6 @@ impl UriPlaylistBin {
}
let element = self.instance();
if current_iteration != state.current_iteration {
state.current_iteration = current_iteration;
element.notify("current-iteration");

View file

@ -88,39 +88,39 @@ impl ElementImpl for CdgDec {
}
impl VideoDecoderImpl for CdgDec {
fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn start(&self) -> Result<(), gst::ErrorMessage> {
let mut out_info = self.output_info.lock().unwrap();
*out_info = None;
self.parent_start(element)
self.parent_start()
}
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
{
let mut cdg_inter = self.cdg_inter.lock().unwrap();
cdg_inter.reset(true);
}
self.parent_stop(element)
self.parent_stop()
}
fn handle_frame(
&self,
element: &Self::Type,
mut frame: gst_video::VideoCodecFrame,
) -> Result<gst::FlowSuccess, gst::FlowError> {
{
let mut out_info = self.output_info.lock().unwrap();
if out_info.is_none() {
let output_state = element.set_output_state(
let instance = self.instance();
let output_state = instance.set_output_state(
gst_video::VideoFormat::Rgba,
CDG_WIDTH,
CDG_HEIGHT,
None,
)?;
element.negotiate(output_state)?;
instance.negotiate(output_state)?;
let out_state = element.output_state().unwrap();
let out_state = instance.output_state().unwrap();
*out_info = Some(out_state.info());
}
}
@ -128,8 +128,8 @@ impl VideoDecoderImpl for CdgDec {
let cmd = {
let input = frame.input_buffer().unwrap();
let map = input.map_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Failed,
["Failed to map input buffer readable"]
);
@ -144,7 +144,7 @@ impl VideoDecoderImpl for CdgDec {
Some(cmd) => cmd,
None => {
// Not a CDG command
element.release_frame(frame);
self.instance().release_frame(frame);
return Ok(gst::FlowSuccess::Ok);
}
};
@ -152,7 +152,7 @@ impl VideoDecoderImpl for CdgDec {
let mut cdg_inter = self.cdg_inter.lock().unwrap();
cdg_inter.handle_cmd(cmd);
element.allocate_output_frame(&mut frame, None)?;
self.instance().allocate_output_frame(&mut frame, None)?;
{
let output = frame.output_buffer_mut().unwrap();
let info = self.output_info.lock().unwrap();
@ -160,8 +160,8 @@ impl VideoDecoderImpl for CdgDec {
let mut out_frame =
gst_video::VideoFrameRef::from_buffer_ref_writable(output, info.as_ref().unwrap())
.map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Failed,
["Failed to map output buffer writable"]
);
@ -188,19 +188,13 @@ impl VideoDecoderImpl for CdgDec {
}
}
gst::debug!(
CAT,
obj: element,
"Finish frame pts={}",
frame.pts().display()
);
gst::debug!(CAT, imp: self, "Finish frame pts={}", frame.pts().display());
element.finish_frame(frame)
self.instance().finish_frame(frame)
}
fn decide_allocation(
&self,
element: &Self::Type,
query: &mut gst::query::Allocation,
) -> Result<(), gst::LoggableError> {
if query
@ -216,11 +210,11 @@ impl VideoDecoderImpl for CdgDec {
}
}
self.parent_decide_allocation(element, query)
self.parent_decide_allocation(query)
}
fn flush(&self, element: &Self::Type) -> bool {
gst::debug!(CAT, obj: element, "flushing, reset CDG interpreter");
fn flush(&self) -> bool {
gst::debug!(CAT, imp: self, "flushing, reset CDG interpreter");
let mut cdg_inter = self.cdg_inter.lock().unwrap();
cdg_inter.reset(false);

View file

@ -111,16 +111,15 @@ fn time_to_bytes(time: gst::ClockTime) -> Bytes {
}
impl BaseParseImpl for CdgParse {
fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
element.set_min_frame_size(CDG_PACKET_SIZE as u32);
fn start(&self) -> Result<(), gst::ErrorMessage> {
self.instance().set_min_frame_size(CDG_PACKET_SIZE as u32);
/* Set duration */
let mut query = gst::query::Duration::new(gst::Format::Bytes);
let pad = element.src_pad();
if pad.query(&mut query) {
if self.instance().src_pad().query(&mut query) {
let size = query.result();
let bytes: Option<Bytes> = size.try_into().unwrap();
element.set_duration(bytes.map(bytes_to_time), 0);
self.instance().set_duration(bytes.map(bytes_to_time), 0);
}
Ok(())
@ -128,11 +127,9 @@ impl BaseParseImpl for CdgParse {
fn handle_frame(
&self,
element: &Self::Type,
mut frame: gst_base::BaseParseFrame,
) -> Result<(gst::FlowSuccess, u32), gst::FlowError> {
let pad = element.src_pad();
if pad.current_caps().is_none() {
if self.instance().src_pad().current_caps().is_none() {
// Set src pad caps
let src_caps = gst::Caps::builder("video/x-cdg")
.field("width", CDG_WIDTH as i32)
@ -141,15 +138,17 @@ impl BaseParseImpl for CdgParse {
.field("parsed", true)
.build();
pad.push_event(gst::event::Caps::new(&src_caps));
self.instance()
.src_pad()
.push_event(gst::event::Caps::new(&src_caps));
}
// Scan for CDG instruction
let input = frame.buffer().unwrap();
let skip = {
let map = input.map_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Failed,
["Failed to map input buffer readable"]
);
@ -172,8 +171,8 @@ impl BaseParseImpl for CdgParse {
let (keyframe, header) = {
let map = input.map_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Failed,
["Failed to map input buffer readable"]
);
@ -203,16 +202,16 @@ impl BaseParseImpl for CdgParse {
buffer.set_flags(gst::BufferFlags::HEADER);
}
gst::debug!(CAT, obj: element, "Found frame pts={}", pts);
gst::debug!(CAT, imp: self, "Found frame pts={}", pts);
element.finish_frame(frame, CDG_PACKET_SIZE as u32)?;
self.instance()
.finish_frame(frame, CDG_PACKET_SIZE as u32)?;
Ok((gst::FlowSuccess::Ok, skip))
}
fn convert(
&self,
_element: &Self::Type,
src_val: impl FormattedValue,
dest_format: gst::Format,
) -> Option<gst::GenericFormattedValue> {

View file

@ -72,9 +72,13 @@ struct CCPacketContents {
}
impl CCDetect {
fn detect_cc_data(data: &[u8]) -> Result<CCPacketContents, ParseError> {
fn detect_cc_data(&self, data: &[u8]) -> Result<CCPacketContents, ParseError> {
if data.len() % 3 != 0 {
gst::warning!(CAT, "cc_data length is not a multiple of 3, truncating");
gst::warning!(
CAT,
imp: self,
"cc_data length is not a multiple of 3, truncating"
);
}
/* logic from ccconverter */
@ -86,6 +90,7 @@ impl CCDetect {
let cc_type = triple[0] & 0x03;
gst::trace!(
CAT,
imp: self,
"triple:{} have ccp:{} 608:{} 708:{} data:{:02x},{:02x},{:02x} cc_valid:{} cc_type:{:02b}",
i * 3,
started_ccp,
@ -130,22 +135,21 @@ impl CCDetect {
})
}
fn detect_cdp(data: &[u8]) -> Result<CCPacketContents, ParseError> {
fn detect_cdp(&self, data: &[u8]) -> Result<CCPacketContents, ParseError> {
let data = extract_cdp(data)?;
Self::detect_cc_data(data)
self.detect_cc_data(data)
}
fn detect(format: CCFormat, data: &[u8]) -> Result<CCPacketContents, ParseError> {
fn detect(&self, format: CCFormat, data: &[u8]) -> Result<CCPacketContents, ParseError> {
match format {
CCFormat::Cc708CcData => Self::detect_cc_data(data),
CCFormat::Cc708Cdp => Self::detect_cdp(data),
CCFormat::Cc708CcData => self.detect_cc_data(data),
CCFormat::Cc708Cdp => self.detect_cdp(data),
}
}
fn maybe_update_properties(
&self,
element: &super::CCDetect,
ts: gst::ClockTime,
cc_packet: CCPacketContents,
) -> Result<(), gst::FlowError> {
@ -160,6 +164,7 @@ impl CCDetect {
gst::trace!(
CAT,
imp: self,
"packet contains {:?} current settings {:?} and state {:?}",
cc_packet,
settings,
@ -193,14 +198,20 @@ impl CCDetect {
state.last_cc708_change = Some(ts);
}
gst::trace!(CAT, "changed to settings {:?} state {:?}", settings, state);
gst::trace!(
CAT,
imp: self,
"changed to settings {:?} state {:?}",
settings,
state
);
}
if notify_cc608 {
element.notify("cc608");
self.instance().notify("cc608");
}
if notify_cc708 {
element.notify("cc708");
self.instance().notify("cc708");
}
Ok(())
@ -243,13 +254,7 @@ impl ObjectImpl for CCDetect {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"window" => {
let mut settings = self.settings.lock().unwrap();
@ -260,7 +265,7 @@ impl ObjectImpl for CCDetect {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"window" => {
let settings = self.settings.lock().unwrap();
@ -337,14 +342,13 @@ impl BaseTransformImpl for CCDetect {
fn transform_ip_passthrough(
&self,
element: &Self::Type,
buf: &gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let map = buf.map_readable().map_err(|_| gst::FlowError::Error)?;
let pts = buf.pts().ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Input buffers must have valid timestamps"]
);
@ -357,11 +361,11 @@ impl BaseTransformImpl for CCDetect {
state.format
};
let cc_packet = match Self::detect(format, map.as_slice()) {
let cc_packet = match self.detect(format, map.as_slice()) {
Ok(v) => v,
Err(e) => {
gst::warning!(CAT, "{}", &e.to_string());
gst::element_warning!(element, gst::StreamError::Decode, [&e.to_string()]);
gst::warning!(CAT, imp: self, "{}", &e.to_string());
gst::element_imp_warning!(self, gst::StreamError::Decode, [&e.to_string()]);
CCPacketContents {
cc608: false,
cc708: false,
@ -369,35 +373,29 @@ impl BaseTransformImpl for CCDetect {
}
};
self.maybe_update_properties(element, pts, cc_packet)
self.maybe_update_properties(pts, cc_packet)
.map_err(|_| gst::FlowError::Error)?;
Ok(gst::FlowSuccess::Ok)
}
fn sink_event(&self, element: &Self::Type, event: gst::Event) -> bool {
fn sink_event(&self, event: gst::Event) -> bool {
match event.view() {
gst::event::EventView::Gap(gap) => {
let _ = self.maybe_update_properties(
element,
gap.get().0,
CCPacketContents {
cc608: false,
cc708: false,
},
);
self.parent_sink_event(element, event)
self.parent_sink_event(event)
}
_ => self.parent_sink_event(element, event),
_ => self.parent_sink_event(event),
}
}
fn set_caps(
&self,
_element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
fn set_caps(&self, incaps: &gst::Caps, outcaps: &gst::Caps) -> Result<(), gst::LoggableError> {
if incaps != outcaps {
return Err(gst::loggable_error!(
CAT,
@ -427,7 +425,7 @@ impl BaseTransformImpl for CCDetect {
Ok(())
}
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
// Drop state
let _ = self.state.lock().unwrap().take();

View file

@ -96,17 +96,13 @@ impl Cea608Overlay {
// https://blogs.gnome.org/mclasen/2019/07/27/more-text-rendering-updates/
//
// TODO: switch to the API presented in this post once it's been exposed
fn recalculate_layout(
&self,
element: &super::Cea608Overlay,
state: &mut State,
) -> Result<gst::FlowSuccess, gst::FlowError> {
fn recalculate_layout(&self, state: &mut State) -> Result<gst::FlowSuccess, gst::FlowError> {
let video_info = state.video_info.as_ref().unwrap();
let fontmap = match pangocairo::FontMap::new() {
Some(fontmap) => Ok(fontmap),
None => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::LibraryError::Failed,
["Failed to create pangocairo font map"]
);
@ -116,8 +112,8 @@ impl Cea608Overlay {
let context = match fontmap.create_context() {
Some(context) => Ok(context),
None => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::LibraryError::Failed,
["Failed to create font map context"]
);
@ -163,7 +159,7 @@ impl Cea608Overlay {
Ok(gst::FlowSuccess::Ok)
}
fn overlay_text(&self, element: &super::Cea608Overlay, text: &str, state: &mut State) {
fn overlay_text(&self, text: &str, state: &mut State) {
let video_info = state.video_info.as_ref().unwrap();
let layout = state.layout.as_ref().unwrap();
layout.set_text(text);
@ -251,7 +247,7 @@ impl Cea608Overlay {
let buffer = match render_buffer() {
Some(buffer) => buffer,
None => {
gst::error!(CAT, obj: element, "Failed to render buffer");
gst::error!(CAT, imp: self, "Failed to render buffer");
state.composition = None;
return;
}
@ -272,16 +268,12 @@ impl Cea608Overlay {
};
}
fn negotiate(
&self,
element: &super::Cea608Overlay,
state: &mut State,
) -> Result<gst::FlowSuccess, gst::FlowError> {
fn negotiate(&self, state: &mut State) -> Result<gst::FlowSuccess, gst::FlowError> {
let video_info = match state.video_info.as_ref() {
Some(video_info) => Ok(video_info),
None => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Negotiation,
["Element hasn't received valid video caps at negotiation time"]
);
@ -322,14 +314,7 @@ impl Cea608Overlay {
}
}
fn decode_cc_data(
&self,
pad: &gst::Pad,
element: &super::Cea608Overlay,
state: &mut State,
data: &[u8],
pts: gst::ClockTime,
) {
fn decode_cc_data(&self, pad: &gst::Pad, state: &mut State, data: &[u8], pts: gst::ClockTime) {
if data.len() % 3 != 0 {
gst::warning!(CAT, "cc_data length is not a multiple of 3, truncating");
}
@ -342,12 +327,7 @@ impl Cea608Overlay {
if cc_type == 0x00 || cc_type == 0x01 {
if state.selected_field.is_none() {
state.selected_field = Some(cc_type);
gst::info!(
CAT,
obj: element,
"Selected field {} automatically",
cc_type
);
gst::info!(CAT, imp: self, "Selected field {} automatically", cc_type);
}
if Some(cc_type) == state.selected_field {
@ -368,10 +348,10 @@ impl Cea608Overlay {
}
};
self.overlay_text(element, &text, state);
self.overlay_text(&text, state);
}
Ok(Status::Clear) => {
self.overlay_text(element, "", state);
self.overlay_text("", state);
}
Ok(Status::Ok) => (),
Err(err) => {
@ -393,14 +373,7 @@ impl Cea608Overlay {
}
}
fn decode_s334_1a(
&self,
pad: &gst::Pad,
element: &super::Cea608Overlay,
state: &mut State,
data: &[u8],
pts: gst::ClockTime,
) {
fn decode_s334_1a(&self, pad: &gst::Pad, state: &mut State, data: &[u8], pts: gst::ClockTime) {
if data.len() % 3 != 0 {
gst::warning!(CAT, "cc_data length is not a multiple of 3, truncating");
}
@ -409,12 +382,7 @@ impl Cea608Overlay {
let cc_type = triple[0] & 0x01;
if state.selected_field.is_none() {
state.selected_field = Some(cc_type);
gst::info!(
CAT,
obj: element,
"Selected field {} automatically",
cc_type
);
gst::info!(CAT, imp: self, "Selected field {} automatically", cc_type);
}
if Some(cc_type) == state.selected_field {
@ -430,7 +398,7 @@ impl Cea608Overlay {
}
};
self.overlay_text(element, &text, state);
self.overlay_text(&text, state);
}
self.reset_timeout(state, pts);
@ -445,7 +413,6 @@ impl Cea608Overlay {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::Cea608Overlay,
mut buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@ -458,28 +425,28 @@ impl Cea608Overlay {
let mut state = self.state.lock().unwrap();
if self.srcpad.check_reconfigure() {
self.negotiate(element, &mut state)?;
self.negotiate(&mut state)?;
}
if state.layout.is_none() {
self.recalculate_layout(element, &mut state)?;
self.recalculate_layout(&mut state)?;
}
for meta in buffer.iter_meta::<gst_video::VideoCaptionMeta>() {
if meta.caption_type() == gst_video::VideoCaptionType::Cea708Cdp {
match extract_cdp(meta.data()) {
Ok(data) => {
self.decode_cc_data(pad, element, &mut state, data, pts);
self.decode_cc_data(pad, &mut state, data, pts);
}
Err(e) => {
gst::warning!(CAT, "{}", &e.to_string());
gst::element_warning!(element, gst::StreamError::Decode, [&e.to_string()]);
gst::element_imp_warning!(self, gst::StreamError::Decode, [&e.to_string()]);
}
}
} else if meta.caption_type() == gst_video::VideoCaptionType::Cea708Raw {
self.decode_cc_data(pad, element, &mut state, meta.data(), pts);
self.decode_cc_data(pad, &mut state, meta.data(), pts);
} else if meta.caption_type() == gst_video::VideoCaptionType::Cea608S3341a {
self.decode_s334_1a(pad, element, &mut state, meta.data(), pts);
self.decode_s334_1a(pad, &mut state, meta.data(), pts);
} else if meta.caption_type() == gst_video::VideoCaptionType::Cea608Raw {
let data = meta.data();
assert!(data.len() % 2 == 0);
@ -500,7 +467,7 @@ impl Cea608Overlay {
}
};
self.overlay_text(element, &text, &mut state);
self.overlay_text(&text, &mut state);
}
self.reset_timeout(&mut state, pts);
@ -511,7 +478,7 @@ impl Cea608Overlay {
if let Some(timeout) = self.settings.lock().unwrap().timeout {
if let Some(interval) = pts.opt_saturating_sub(state.last_cc_pts) {
if interval > timeout {
gst::info!(CAT, obj: element, "Reached timeout, clearing overlay");
gst::info!(CAT, imp: self, "Reached timeout, clearing overlay");
state.composition.take();
state.last_cc_pts.take();
}
@ -539,12 +506,7 @@ impl Cea608Overlay {
self.srcpad.push(buffer)
}
fn sink_event(
&self,
pad: &gst::Pad,
element: &super::Cea608Overlay,
event: gst::Event,
) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -553,7 +515,7 @@ impl Cea608Overlay {
let mut state = self.state.lock().unwrap();
state.video_info = gst_video::VideoInfo::from_caps(c.caps()).ok();
self.srcpad.check_reconfigure();
match self.negotiate(element, &mut state) {
match self.negotiate(&mut state) {
Ok(_) => true,
Err(_) => {
self.srcpad.mark_reconfigure();
@ -565,9 +527,9 @@ impl Cea608Overlay {
let mut state = self.state.lock().unwrap();
state.caption_frame = CaptionFrame::default();
state.composition = None;
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
}
@ -585,14 +547,14 @@ impl ObjectSubclass for Cea608Overlay {
Cea608Overlay::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|overlay, element| overlay.sink_chain(pad, element, buffer),
|overlay| overlay.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
Cea608Overlay::catch_panic_pad_function(
parent,
|| false,
|overlay, element| overlay.sink_event(pad, element, event),
|overlay| overlay.sink_event(pad, event),
)
})
.flags(gst::PadFlags::PROXY_CAPS)
@ -645,13 +607,7 @@ impl ObjectImpl for Cea608Overlay {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"field" => {
let mut settings = self.settings.lock().unwrap();
@ -684,7 +640,7 @@ impl ObjectImpl for Cea608Overlay {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"field" => {
let settings = self.settings.lock().unwrap();
@ -705,9 +661,10 @@ impl ObjectImpl for Cea608Overlay {
_ => unimplemented!(),
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -760,10 +717,9 @@ impl ElementImpl for Cea608Overlay {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused | gst::StateChange::PausedToReady => {
@ -779,6 +735,6 @@ impl ElementImpl for Cea608Overlay {
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -393,7 +393,7 @@ fn eia608_to_text(cc_data: u16) -> String {
}
fn dump(
element: &super::Cea608ToJson,
imp: &Cea608ToJson,
cc_data: u16,
pts: impl Into<Option<gst::ClockTime>>,
duration: impl Into<Option<gst::ClockTime>>,
@ -404,7 +404,7 @@ fn dump(
if cc_data != 0x8080 {
gst::debug!(
CAT,
obj: element,
imp: imp,
"{} -> {}: {}",
pts.display(),
end.display(),
@ -413,7 +413,7 @@ fn dump(
} else {
gst::trace!(
CAT,
obj: element,
imp: imp,
"{} -> {}: padding",
pts.display(),
end.display()
@ -422,21 +422,17 @@ fn dump(
}
impl State {
fn update_mode(
&mut self,
element: &super::Cea608ToJson,
mode: Cea608Mode,
) -> Option<TimestampedLines> {
fn update_mode(&mut self, imp: &Cea608ToJson, mode: Cea608Mode) -> Option<TimestampedLines> {
if mode.is_rollup() && self.mode == Some(Cea608Mode::PopOn) {
// https://www.law.cornell.edu/cfr/text/47/79.101 (f)(2)(v)
let _ = self.drain(element, true);
let _ = self.drain(imp, true);
}
let ret = if Some(mode) != self.mode {
if self.mode == Some(Cea608Mode::PopOn) {
self.drain_pending(element)
self.drain_pending(imp)
} else {
self.drain(element, true)
self.drain(imp, true)
}
} else {
None
@ -459,8 +455,8 @@ impl State {
ret
}
fn drain(&mut self, element: &super::Cea608ToJson, flush: bool) -> Option<TimestampedLines> {
gst::log!(CAT, obj: element, "Draining");
fn drain(&mut self, imp: &Cea608ToJson, flush: bool) -> Option<TimestampedLines> {
gst::log!(CAT, imp: imp, "Draining");
let pts = if self.settings.unbuffered {
self.current_pts
@ -533,9 +529,9 @@ impl State {
}
}
fn drain_pending(&mut self, element: &super::Cea608ToJson) -> Option<TimestampedLines> {
fn drain_pending(&mut self, imp: &Cea608ToJson) -> Option<TimestampedLines> {
if let Some(mut pending) = self.pending_lines.take() {
gst::log!(CAT, obj: element, "Draining pending");
gst::log!(CAT, imp: imp, "Draining pending");
pending.duration = self
.current_pts
.opt_add(self.current_duration)
@ -548,18 +544,14 @@ impl State {
}
}
fn decode_preamble(
&mut self,
element: &super::Cea608ToJson,
cc_data: u16,
) -> Option<TimestampedLines> {
fn decode_preamble(&mut self, imp: &Cea608ToJson, cc_data: u16) -> Option<TimestampedLines> {
let preamble = parse_preamble(cc_data);
if preamble.chan != 0 {
return None;
}
gst::log!(CAT, obj: element, "preamble: {:?}", preamble);
gst::log!(CAT, imp: imp, "preamble: {:?}", preamble);
let drain_roll_up = self.cursor.row != preamble.row as u32;
@ -606,7 +598,7 @@ impl State {
if self.settings.unbuffered {
/* We only need to drain when the roll-up window was relocated */
let ret = if drain_roll_up {
self.drain(element, true)
self.drain(imp, true)
} else {
None
};
@ -620,7 +612,7 @@ impl State {
ret
// The relocation is potentially destructive, let us drain
} else {
let ret = self.drain(element, true);
let ret = self.drain(imp, true);
self.rows.insert(self.cursor.row, Row::new(self.cursor.row));
ret
@ -638,14 +630,10 @@ impl State {
}
}
fn decode_control(
&mut self,
element: &super::Cea608ToJson,
cc_data: u16,
) -> Option<TimestampedLines> {
fn decode_control(&mut self, imp: &Cea608ToJson, cc_data: u16) -> Option<TimestampedLines> {
let (cmd, chan) = parse_control(cc_data);
gst::log!(CAT, obj: element, "Command for CC {}", chan);
gst::log!(CAT, imp: imp, "Command for CC {}", chan);
if chan != 0 {
return None;
@ -653,32 +641,32 @@ impl State {
match cmd {
ffi::eia608_control_t_eia608_control_resume_direct_captioning => {
return self.update_mode(element, Cea608Mode::PaintOn);
return self.update_mode(imp, Cea608Mode::PaintOn);
}
ffi::eia608_control_t_eia608_control_erase_display_memory => {
return match self.mode {
Some(Cea608Mode::PopOn) => {
self.clear = Some(true);
self.drain_pending(element)
self.drain_pending(imp)
}
_ => {
let ret = self.drain(element, true);
let ret = self.drain(imp, true);
self.clear = Some(true);
ret
}
};
}
ffi::eia608_control_t_eia608_control_roll_up_2 => {
return self.update_mode(element, Cea608Mode::RollUp2);
return self.update_mode(imp, Cea608Mode::RollUp2);
}
ffi::eia608_control_t_eia608_control_roll_up_3 => {
return self.update_mode(element, Cea608Mode::RollUp3);
return self.update_mode(imp, Cea608Mode::RollUp3);
}
ffi::eia608_control_t_eia608_control_roll_up_4 => {
return self.update_mode(element, Cea608Mode::RollUp4);
return self.update_mode(imp, Cea608Mode::RollUp4);
}
ffi::eia608_control_t_eia608_control_carriage_return => {
gst::log!(CAT, obj: element, "carriage return");
gst::log!(CAT, imp: imp, "carriage return");
if let Some(mode) = self.mode {
// https://www.law.cornell.edu/cfr/text/47/79.101 (f)(2)(i) (f)(3)(i)
@ -704,9 +692,9 @@ impl State {
}
self.rows.insert(self.cursor.row, Row::new(self.cursor.row));
self.drain(element, false)
self.drain(imp, false)
} else {
let ret = self.drain(element, true);
let ret = self.drain(imp, true);
self.carriage_return = Some(true);
ret
};
@ -721,7 +709,7 @@ impl State {
}
}
ffi::eia608_control_t_eia608_control_resume_caption_loading => {
return self.update_mode(element, Cea608Mode::PopOn);
return self.update_mode(imp, Cea608Mode::PopOn);
}
ffi::eia608_control_t_eia608_control_erase_non_displayed_memory => {
if self.mode == Some(Cea608Mode::PopOn) {
@ -730,13 +718,13 @@ impl State {
}
ffi::eia608_control_t_eia608_control_end_of_caption => {
// https://www.law.cornell.edu/cfr/text/47/79.101 (f)(2)
self.update_mode(element, Cea608Mode::PopOn);
self.update_mode(imp, Cea608Mode::PopOn);
self.first_pts = self.current_pts;
let ret = if self.settings.unbuffered {
self.drain(element, true)
self.drain(imp, true)
} else {
let ret = self.drain_pending(element);
self.pending_lines = self.drain(element, true);
let ret = self.drain_pending(imp);
self.pending_lines = self.drain(imp, true);
ret
};
return ret;
@ -756,14 +744,14 @@ impl State {
| ffi::eia608_control_t_eia608_control_text_restart
| ffi::eia608_control_t_eia608_control_text_resume_text_display => {}
_ => {
gst::warning!(CAT, obj: element, "Unknown command {}!", cmd);
gst::warning!(CAT, imp: imp, "Unknown command {}!", cmd);
}
}
None
}
fn decode_text(&mut self, element: &super::Cea608ToJson, cc_data: u16) {
fn decode_text(&mut self, imp: &Cea608ToJson, cc_data: u16) {
let (char1, char2, chan) = eia608_to_utf8(cc_data);
if chan != 0 {
@ -791,7 +779,7 @@ impl State {
row.push(&mut self.cursor, c);
}
} else {
gst::warning!(CAT, obj: element, "No row to append decoded text to!");
gst::warning!(CAT, imp: imp, "No row to append decoded text to!");
}
}
@ -807,13 +795,13 @@ impl State {
fn handle_cc_data(
&mut self,
element: &super::Cea608ToJson,
imp: &Cea608ToJson,
pts: Option<gst::ClockTime>,
duration: Option<gst::ClockTime>,
cc_data: u16,
) -> Option<TimestampedLines> {
if (is_specialna(cc_data) || is_control(cc_data)) && Some(cc_data) == self.last_cc_data {
gst::log!(CAT, obj: element, "Skipping duplicate");
gst::log!(CAT, imp: imp, "Skipping duplicate");
return None;
}
@ -822,25 +810,25 @@ impl State {
self.current_duration = duration;
if is_xds(cc_data) {
gst::log!(CAT, obj: element, "XDS, ignoring");
gst::log!(CAT, imp: imp, "XDS, ignoring");
} else if is_control(cc_data) {
gst::log!(CAT, obj: element, "control!");
return self.decode_control(element, cc_data);
gst::log!(CAT, imp: imp, "control!");
return self.decode_control(imp, cc_data);
} else if is_basicna(cc_data) || is_specialna(cc_data) || is_westeu(cc_data) {
if let Some(mode) = self.mode {
self.mode?;
gst::log!(CAT, obj: element, "text");
self.decode_text(element, cc_data);
gst::log!(CAT, imp: imp, "text");
self.decode_text(imp, cc_data);
if mode.is_rollup() && self.settings.unbuffered {
return self.drain(element, false);
return self.drain(imp, false);
}
}
} else if is_preamble(cc_data) {
gst::log!(CAT, obj: element, "preamble");
return self.decode_preamble(element, cc_data);
gst::log!(CAT, imp: imp, "preamble");
return self.decode_preamble(imp, cc_data);
} else if is_midrowchange(cc_data) {
gst::log!(CAT, obj: element, "midrowchange");
gst::log!(CAT, imp: imp, "midrowchange");
self.decode_midrowchange(cc_data);
}
None
@ -848,16 +836,12 @@ impl State {
}
impl Cea608ToJson {
fn output(
&self,
element: &super::Cea608ToJson,
lines: TimestampedLines,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::debug!(CAT, obj: element, "outputting: {:?}", lines);
fn output(&self, lines: TimestampedLines) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::debug!(CAT, imp: self, "outputting: {:?}", lines);
let json = serde_json::to_string(&lines.lines).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Write,
["Failed to serialize as json {}", err]
);
@ -872,7 +856,7 @@ impl Cea608ToJson {
buf_mut.set_duration(lines.duration);
}
gst::log!(CAT, obj: element, "Pushing {:?}", buf);
gst::log!(CAT, imp: self, "Pushing {:?}", buf);
self.srcpad.push(buf)
}
@ -880,7 +864,6 @@ impl Cea608ToJson {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::Cea608ToJson,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::trace!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@ -913,11 +896,11 @@ impl Cea608ToJson {
let cc_data = (data[0] as u16) << 8 | data[1] as u16;
dump(element, cc_data, pts, duration);
dump(self, cc_data, pts, duration);
if let Some(lines) = state.handle_cc_data(element, pts, duration, cc_data) {
if let Some(lines) = state.handle_cc_data(self, pts, duration, cc_data) {
drop(state);
self.output(element, lines)
self.output(lines)
} else if state.settings.unbuffered {
drop(state);
self.srcpad.push_event(
@ -931,7 +914,7 @@ impl Cea608ToJson {
}
}
fn sink_event(&self, pad: &gst::Pad, element: &super::Cea608ToJson, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -949,19 +932,19 @@ impl Cea608ToJson {
*state = State::default();
state.settings = old_settings;
drop(state);
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::Eos(..) => {
if let Some(lines) = self.state.borrow_mut().drain_pending(element) {
let _ = self.output(element, lines);
if let Some(lines) = self.state.borrow_mut().drain_pending(self) {
let _ = self.output(lines);
}
if let Some(lines) = self.state.borrow_mut().drain(element, true) {
let _ = self.output(element, lines);
if let Some(lines) = self.state.borrow_mut().drain(self, true) {
let _ = self.output(lines);
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
}
@ -979,14 +962,14 @@ impl ObjectSubclass for Cea608ToJson {
Cea608ToJson::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
|this| this.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
Cea608ToJson::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
|this| this.sink_event(pad, event),
)
})
.flags(gst::PadFlags::FIXED_CAPS)
@ -1007,9 +990,10 @@ impl ObjectSubclass for Cea608ToJson {
}
impl ObjectImpl for Cea608ToJson {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -1030,13 +1014,7 @@ impl ObjectImpl for Cea608ToJson {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"unbuffered" => {
self.settings.lock().unwrap().unbuffered =
@ -1046,7 +1024,7 @@ impl ObjectImpl for Cea608ToJson {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"unbuffered" => {
let settings = self.settings.lock().unwrap();
@ -1106,10 +1084,9 @@ impl ElementImpl for Cea608ToJson {
#[allow(clippy::single_match)]
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused => {
@ -1120,7 +1097,7 @@ impl ElementImpl for Cea608ToJson {
_ => (),
}
let ret = self.parent_change_state(element, transition)?;
let ret = self.parent_change_state(transition)?;
match transition {
gst::StateChange::PausedToReady => {

View file

@ -61,7 +61,6 @@ impl Cea608ToTt {
fn sink_chain(
&self,
pad: &gst::Pad,
_element: &super::Cea608ToTt,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@ -267,7 +266,7 @@ impl Cea608ToTt {
buffer
}
fn sink_event(&self, pad: &gst::Pad, element: &super::Cea608ToTt, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -368,7 +367,7 @@ impl Cea608ToTt {
_ => (),
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
}
@ -385,14 +384,14 @@ impl ObjectSubclass for Cea608ToTt {
Cea608ToTt::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
|this| this.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
Cea608ToTt::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
|this| this.sink_event(pad, event),
)
})
.flags(gst::PadFlags::FIXED_CAPS)
@ -412,9 +411,10 @@ impl ObjectSubclass for Cea608ToTt {
}
impl ObjectImpl for Cea608ToTt {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -486,10 +486,9 @@ impl ElementImpl for Cea608ToTt {
#[allow(clippy::single_match)]
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused => {
@ -499,7 +498,7 @@ impl ElementImpl for Cea608ToTt {
_ => (),
}
let ret = self.parent_change_state(element, transition)?;
let ret = self.parent_change_state(transition)?;
match transition {
gst::StateChange::PausedToReady => {

View file

@ -7,7 +7,6 @@
//
// SPDX-License-Identifier: MPL-2.0
use gst::element_error;
use gst::glib;
use gst::prelude::*;
use gst::subclass::prelude::*;
@ -351,7 +350,6 @@ impl JsonToVtt {
fn sink_chain(
&self,
pad: &gst::Pad,
_element: &super::JsonToVtt,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::trace!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@ -370,7 +368,7 @@ impl JsonToVtt {
state.keyunit_requests.push(fku);
}
fn src_event(&self, pad: &gst::Pad, element: &super::JsonToVtt, event: gst::Event) -> bool {
fn src_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -388,20 +386,20 @@ impl JsonToVtt {
}
Err(_) => gst::warning!(
CAT,
obj: element,
imp: self,
"Invalid force-key-unit event received from downstream: {:?}",
&ev
),
}
}
pad.event_default(Some(element), event);
pad.event_default(Some(&*self.instance()), event);
true
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn sink_event(&self, pad: &gst::Pad, element: &super::JsonToVtt, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -412,7 +410,7 @@ impl JsonToVtt {
let buffers = state.handle_eos();
drop(state);
let _ = self.output(buffers);
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::Caps(..) => {
let mut downstream_caps = match self.srcpad.allowed_caps() {
@ -455,8 +453,8 @@ impl JsonToVtt {
state.segment = s;
}
Err(err) => {
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Failed,
["Time segment needed: {:?}", err]
);
@ -465,7 +463,7 @@ impl JsonToVtt {
};
/* FIXME: Handle segment updates by draining? */
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::Gap(ev) => {
gst::log!(CAT, obj: pad, "Handling gap {:?}", ev);
@ -475,7 +473,7 @@ impl JsonToVtt {
let _ = self.output(buffers);
true
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
@ -501,14 +499,14 @@ impl ObjectSubclass for JsonToVtt {
JsonToVtt::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
|this| this.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
JsonToVtt::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
|this| this.sink_event(pad, event),
)
})
.flags(gst::PadFlags::FIXED_CAPS)
@ -521,7 +519,7 @@ impl ObjectSubclass for JsonToVtt {
JsonToVtt::catch_panic_pad_function(
parent,
|| false,
|this, element| this.src_event(pad, element, event),
|this| this.src_event(pad, event),
)
})
.build();
@ -535,9 +533,10 @@ impl ObjectSubclass for JsonToVtt {
}
impl ObjectImpl for JsonToVtt {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -593,17 +592,16 @@ impl ElementImpl for JsonToVtt {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
if transition == gst::StateChange::ReadyToPaused {
let mut state = self.state.lock().unwrap();
*state = State::default();
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -246,7 +246,6 @@ impl MccEnc {
fn generate_caption(
&self,
element: &super::MccEnc,
state: &State,
buffer: &gst::Buffer,
outbuf: &mut Vec<u8>,
@ -254,8 +253,8 @@ impl MccEnc {
let meta = buffer
.meta::<gst_video::VideoTimeCodeMeta>()
.ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Stream with timecodes on each buffer required"]
);
@ -266,8 +265,8 @@ impl MccEnc {
let _ = write!(outbuf, "{}\t", meta.tc());
let map = buffer.map_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Failed to map buffer readable"]
);
@ -277,8 +276,8 @@ impl MccEnc {
let len = map.len();
if len >= 256 {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Too big buffer: {}", map.len()]
);
@ -314,7 +313,6 @@ impl MccEnc {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::MccEnc,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@ -327,7 +325,7 @@ impl MccEnc {
self.generate_headers(&*state, &mut outbuf)?;
}
self.generate_caption(element, &*state, &buffer, &mut outbuf)?;
self.generate_caption(&*state, &buffer, &mut outbuf)?;
let mut buf = gst::Buffer::from_mut_slice(outbuf);
buffer
@ -338,7 +336,7 @@ impl MccEnc {
self.srcpad.push(buf)
}
fn sink_event(&self, pad: &gst::Pad, element: &super::MccEnc, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -377,11 +375,11 @@ impl MccEnc {
.build();
self.srcpad.push_event(gst::event::Caps::new(&caps))
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_event(&self, pad: &gst::Pad, element: &super::MccEnc, event: gst::Event) -> bool {
fn src_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -390,16 +388,11 @@ impl MccEnc {
gst::log!(CAT, obj: pad, "Dropping seek event");
false
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::MccEnc,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
@ -415,7 +408,7 @@ impl MccEnc {
);
true
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
}
@ -433,33 +426,21 @@ impl ObjectSubclass for MccEnc {
MccEnc::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|enc, element| enc.sink_chain(pad, element, buffer),
|enc| enc.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
MccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.sink_event(pad, element, event),
)
MccEnc::catch_panic_pad_function(parent, || false, |enc| enc.sink_event(pad, event))
})
.build();
let templ = klass.pad_template("src").unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
.event_function(|pad, parent, event| {
MccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_event(pad, element, event),
)
MccEnc::catch_panic_pad_function(parent, || false, |enc| enc.src_event(pad, event))
})
.query_function(|pad, parent, query| {
MccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_query(pad, element, query),
)
MccEnc::catch_panic_pad_function(parent, || false, |enc| enc.src_query(pad, query))
})
.build();
@ -492,13 +473,7 @@ impl ObjectImpl for MccEnc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"uuid" => {
let mut settings = self.settings.lock().unwrap();
@ -512,7 +487,7 @@ impl ObjectImpl for MccEnc {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"uuid" => {
let settings = self.settings.lock().unwrap();
@ -526,9 +501,10 @@ impl ObjectImpl for MccEnc {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -603,10 +579,9 @@ impl ElementImpl for MccEnc {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused | gst::StateChange::PausedToReady => {
@ -617,6 +592,6 @@ impl ElementImpl for MccEnc {
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -9,7 +9,6 @@
use gst::glib;
use gst::prelude::*;
use gst::subclass::prelude::*;
use gst::{element_error, loggable_error};
use gst_video::ValidVideoTimeCode;
use std::cmp;
@ -44,10 +43,12 @@ struct PullState {
}
impl PullState {
fn new(element: &super::MccParse, pad: &gst::Pad) -> Self {
fn new(imp: &MccParse, pad: &gst::Pad) -> Self {
Self {
need_stream_start: true,
stream_id: pad.create_stream_id(element, Some("src")).to_string(),
stream_id: pad
.create_stream_id(&*imp.instance(), Some("src"))
.to_string(),
offset: 0,
duration: gst::ClockTime::NONE,
}
@ -166,7 +167,7 @@ impl State {
fn handle_timecode(
&mut self,
element: &super::MccParse,
imp: &MccParse,
framerate: gst::Fraction,
drop_frame: bool,
tc: TimeCode,
@ -179,8 +180,8 @@ impl State {
.as_ref()
.map(Clone::clone)
.ok_or_else(|| {
element_error!(
element,
gst::element_imp_error!(
imp,
gst::StreamError::Decode,
["Invalid first timecode {:?}", timecode]
);
@ -190,7 +191,7 @@ impl State {
gst::warning!(
CAT,
obj: element,
imp: imp,
"Invalid timecode {:?}, using previous {:?}",
timecode,
last_timecode
@ -203,11 +204,7 @@ impl State {
/// Calculate a timestamp from the timecode and make sure to
/// not produce timestamps jumping backwards
fn update_timestamp(
&mut self,
element: &super::MccParse,
timecode: &gst_video::ValidVideoTimeCode,
) {
fn update_timestamp(&mut self, imp: &MccParse, timecode: &gst_video::ValidVideoTimeCode) {
let nsecs = timecode.time_since_daily_jam();
if self.start_position.is_none() {
self.start_position = Some(nsecs);
@ -217,7 +214,7 @@ impl State {
let nsecs = nsecs.checked_sub(start_position).unwrap_or_else(|| {
gst::fixme!(
CAT,
obj: element,
imp: imp,
"New position {} < start position {}",
nsecs,
start_position,
@ -233,7 +230,7 @@ impl State {
} else {
gst::fixme!(
CAT,
obj: element,
imp: imp,
"New position {} < last position {}",
nsecs,
self.last_position.display(),
@ -243,7 +240,7 @@ impl State {
fn add_buffer_metadata(
&mut self,
element: &super::MccParse,
imp: &MccParse,
buffer: &mut gst::buffer::Buffer,
timecode: &gst_video::ValidVideoTimeCode,
framerate: gst::Fraction,
@ -251,7 +248,7 @@ impl State {
let buffer = buffer.get_mut().unwrap();
gst_video::VideoTimeCodeMeta::add(buffer, timecode);
self.update_timestamp(element, timecode);
self.update_timestamp(imp, timecode);
buffer.set_pts(self.last_position);
@ -267,7 +264,7 @@ impl State {
fn create_events(
&mut self,
element: &super::MccParse,
imp: &MccParse,
format: Option<Format>,
framerate: gst::Fraction,
) -> Vec<gst::Event> {
@ -307,7 +304,7 @@ impl State {
};
events.push(gst::event::Caps::new(&caps));
gst::info!(CAT, obj: element, "Caps changed to {:?}", &caps);
gst::info!(CAT, imp: imp, "Caps changed to {:?}", &caps);
}
}
@ -355,7 +352,6 @@ impl AsMut<[u8]> for OffsetVec {
impl MccParse {
fn handle_buffer(
&self,
element: &super::MccParse,
buffer: Option<gst::Buffer>,
scan_tc_rate: bool,
) -> Result<gst::FlowSuccess, gst::FlowError> {
@ -363,8 +359,8 @@ impl MccParse {
let drain = if let Some(buffer) = buffer {
let buffer = buffer.into_mapped_buffer_readable().map_err(|_| {
element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to map buffer readable"]
);
@ -386,15 +382,15 @@ impl MccParse {
gst::debug!(
CAT,
obj: element,
imp: self,
"Got caption buffer with timecode {:?} and size {}",
tc,
data.len()
);
if scan_tc_rate {
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Found caption line while scanning for timecode rate"]
);
@ -403,12 +399,7 @@ impl MccParse {
}
if data.len() < 3 {
gst::debug!(
CAT,
obj: element,
"Too small caption packet: {}",
data.len(),
);
gst::debug!(CAT, imp: self, "Too small caption packet: {}", data.len(),);
continue;
}
@ -416,7 +407,7 @@ impl MccParse {
(0x61, 0x01) => Format::Cea708Cdp,
(0x61, 0x02) => Format::Cea608,
(did, sdid) => {
gst::debug!(CAT, obj: element, "Unknown DID {:x} SDID {:x}", did, sdid);
gst::debug!(CAT, imp: self, "Unknown DID {:x} SDID {:x}", did, sdid);
continue;
}
};
@ -425,7 +416,7 @@ impl MccParse {
if data.len() < 3 + len as usize {
gst::debug!(
CAT,
obj: element,
imp: self,
"Too small caption packet: {} < {}",
data.len(),
3 + len,
@ -433,14 +424,14 @@ impl MccParse {
continue;
}
state = self.handle_line(element, tc, data, format, state)?;
state = self.handle_line(tc, data, format, state)?;
}
Ok(Some(MccLine::Caption(tc, None))) => {
assert!(state.seeking);
if scan_tc_rate {
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Found caption line while scanning for timecode rate"]
);
@ -448,12 +439,12 @@ impl MccParse {
break Err(gst::FlowError::Error);
}
state = self.handle_skipped_line(element, tc, state)?;
state = self.handle_skipped_line(tc, state)?;
}
Ok(Some(MccLine::TimeCodeRate(rate, df))) => {
gst::debug!(
CAT,
obj: element,
imp: self,
"Got timecode rate {} (drop frame {})",
rate,
df
@ -465,11 +456,11 @@ impl MccParse {
}
}
Ok(Some(line)) => {
gst::debug!(CAT, obj: element, "Got line '{:?}'", line);
gst::debug!(CAT, imp: self, "Got line '{:?}'", line);
}
Err((line, err)) => {
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Couldn't parse line '{:?}': {:?}", line, err]
);
@ -478,8 +469,8 @@ impl MccParse {
}
Ok(None) => {
if scan_tc_rate {
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Found end of input while scanning for timecode rate"]
);
@ -498,12 +489,11 @@ impl MccParse {
fn handle_skipped_line(
&self,
element: &super::MccParse,
tc: TimeCode,
mut state: MutexGuard<State>,
) -> Result<MutexGuard<State>, gst::FlowError> {
let (framerate, drop_frame) = parse_timecode_rate(state.timecode_rate)?;
let timecode = state.handle_timecode(element, framerate, drop_frame, tc)?;
let timecode = state.handle_timecode(self, framerate, drop_frame, tc)?;
let nsecs = timecode.time_since_daily_jam();
state.last_timecode = Some(timecode);
@ -526,15 +516,14 @@ impl MccParse {
fn handle_line(
&self,
element: &super::MccParse,
tc: TimeCode,
data: Vec<u8>,
format: Format,
mut state: MutexGuard<State>,
) -> Result<MutexGuard<State>, gst::FlowError> {
let (framerate, drop_frame) = parse_timecode_rate(state.timecode_rate)?;
let events = state.create_events(element, Some(format), framerate);
let timecode = state.handle_timecode(element, framerate, drop_frame, tc)?;
let events = state.create_events(self, Some(format), framerate);
let timecode = state.handle_timecode(self, framerate, drop_frame, tc)?;
let len = data[2] as usize;
let mut buffer = gst::Buffer::from_mut_slice(OffsetVec {
@ -543,7 +532,7 @@ impl MccParse {
len,
});
state.add_buffer_metadata(element, &mut buffer, &timecode, framerate);
state.add_buffer_metadata(self, &mut buffer, &timecode, framerate);
// Update the last_timecode to the current one
state.last_timecode = Some(timecode);
@ -558,13 +547,13 @@ impl MccParse {
drop(state);
for event in events {
gst::debug!(CAT, obj: element, "Pushing event {:?}", event);
gst::debug!(CAT, imp: self, "Pushing event {:?}", event);
self.srcpad.push_event(event);
}
self.srcpad.push(buffer).map_err(|err| {
if err != gst::FlowError::Flushing && err != gst::FlowError::Eos {
gst::error!(CAT, obj: element, "Pushing buffer returned {:?}", err);
gst::error!(CAT, imp: self, "Pushing buffer returned {:?}", err);
}
err
})?;
@ -576,11 +565,7 @@ impl MccParse {
Ok(self.state.lock().unwrap())
}
fn sink_activate(
&self,
pad: &gst::Pad,
element: &super::MccParse,
) -> Result<(), gst::LoggableError> {
fn sink_activate(&self, pad: &gst::Pad) -> Result<(), gst::LoggableError> {
let mode = {
let mut query = gst::query::Scheduling::new();
let mut state = self.state.lock().unwrap();
@ -595,7 +580,7 @@ impl MccParse {
{
gst::debug!(CAT, obj: pad, "Activating in Pull mode");
state.pull = Some(PullState::new(element, &self.srcpad));
state.pull = Some(PullState::new(self, &self.srcpad));
gst::PadMode::Pull
} else {
@ -608,25 +593,13 @@ impl MccParse {
Ok(())
}
fn start_task(&self, element: &super::MccParse) -> Result<(), gst::LoggableError> {
let element_weak = element.downgrade();
let pad_weak = self.sinkpad.downgrade();
fn start_task(&self) -> Result<(), gst::LoggableError> {
let imp = self.ref_counted();
let res = self.sinkpad.start_task(move || {
let element = match element_weak.upgrade() {
Some(element) => element,
None => {
if let Some(pad) = pad_weak.upgrade() {
let _ = pad.pause_task();
}
return;
}
};
let parse = element.imp();
parse.loop_fn(&element);
imp.loop_fn();
});
if res.is_err() {
return Err(loggable_error!(CAT, "Failed to start pad task"));
return Err(gst::loggable_error!(CAT, "Failed to start pad task"));
}
Ok(())
}
@ -634,13 +607,12 @@ impl MccParse {
fn sink_activatemode(
&self,
_pad: &gst::Pad,
element: &super::MccParse,
mode: gst::PadMode,
active: bool,
) -> Result<(), gst::LoggableError> {
if mode == gst::PadMode::Pull {
if active {
self.start_task(element)?;
self.start_task()?;
} else {
let _ = self.sinkpad.stop_task();
}
@ -649,23 +621,26 @@ impl MccParse {
Ok(())
}
fn scan_duration(
&self,
element: &super::MccParse,
) -> Result<Option<ValidVideoTimeCode>, gst::LoggableError> {
gst::debug!(CAT, obj: element, "Scanning duration");
fn scan_duration(&self) -> Result<Option<ValidVideoTimeCode>, gst::LoggableError> {
gst::debug!(CAT, imp: self, "Scanning duration");
/* First let's query the bytes duration upstream */
let mut q = gst::query::Duration::new(gst::Format::Bytes);
if !self.sinkpad.peer_query(&mut q) {
return Err(loggable_error!(CAT, "Failed to query upstream duration"));
return Err(gst::loggable_error!(
CAT,
"Failed to query upstream duration"
));
}
let size = match q.result().try_into().unwrap() {
Some(gst::format::Bytes(size)) => size,
None => {
return Err(loggable_error!(CAT, "Failed to query upstream duration"));
return Err(gst::loggable_error!(
CAT,
"Failed to query upstream duration"
));
}
};
@ -683,7 +658,7 @@ impl MccParse {
buffers.push(buffer);
}
Err(flow) => {
return Err(loggable_error!(
return Err(gst::loggable_error!(
CAT,
"Failed to pull buffer while scanning duration: {:?}",
flow
@ -698,7 +673,7 @@ impl MccParse {
let buf = buf
.clone()
.into_mapped_buffer_readable()
.map_err(|_| loggable_error!(CAT, "Failed to map buffer readable"))?;
.map_err(|_| gst::loggable_error!(CAT, "Failed to map buffer readable"))?;
reader.push(buf);
}
@ -709,7 +684,7 @@ impl MccParse {
{
let state = self.state.lock().unwrap();
let (framerate, drop_frame) = parse_timecode_rate(state.timecode_rate)
.map_err(|_| loggable_error!(CAT, "Failed to parse timecode rate"))?;
.map_err(|_| gst::loggable_error!(CAT, "Failed to parse timecode rate"))?;
if let Ok(mut timecode) = parse_timecode(framerate, drop_frame, tc) {
/* We're looking for the total duration */
timecode.increment_frame();
@ -720,18 +695,13 @@ impl MccParse {
}
if last_tc.is_some() || offset == 0 {
gst::debug!(
CAT,
obj: element,
"Duration scan done, last_tc: {:?}",
last_tc
);
gst::debug!(CAT, imp: self, "Duration scan done, last_tc: {:?}", last_tc);
break (Ok(last_tc));
}
}
}
fn push_eos(&self, element: &super::MccParse) {
fn push_eos(&self) {
let mut state = self.state.lock().unwrap();
if state.seeking {
@ -740,7 +710,7 @@ impl MccParse {
match parse_timecode_rate(state.timecode_rate) {
Ok((framerate, _)) => {
let mut events = state.create_events(element, None, framerate);
let mut events = state.create_events(self, None, framerate);
let mut eos_event = gst::event::Eos::builder();
if let Some(seek_seqnum) = state.seek_seqnum {
@ -753,13 +723,13 @@ impl MccParse {
drop(state);
for event in events {
gst::debug!(CAT, obj: element, "Pushing event {:?}", event);
gst::debug!(CAT, imp: self, "Pushing event {:?}", event);
self.srcpad.push_event(event);
}
}
Err(_) => {
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Failed,
["Streaming stopped, failed to parse timecode rate"]
);
@ -767,7 +737,7 @@ impl MccParse {
}
}
fn loop_fn(&self, element: &super::MccParse) {
fn loop_fn(&self) {
let mut state = self.state.lock().unwrap();
let State {
timecode_rate: ref tc_rate,
@ -794,8 +764,8 @@ impl MccParse {
Err(flow) => {
gst::error!(CAT, obj: &self.sinkpad, "Failed to pull, reason: {:?}", flow);
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Failed,
["Streaming stopped, failed to pull buffer"]
);
@ -805,11 +775,11 @@ impl MccParse {
}
};
match self.handle_buffer(element, buffer, scan_tc_rate) {
match self.handle_buffer(buffer, scan_tc_rate) {
Ok(_) => {
let tc_rate = self.state.lock().unwrap().timecode_rate;
if scan_tc_rate && tc_rate.is_some() {
match self.scan_duration(element) {
match self.scan_duration() {
Ok(Some(tc)) => {
let mut state = self.state.lock().unwrap();
let mut pull = state.pull.as_mut().unwrap();
@ -823,8 +793,8 @@ impl MccParse {
Err(err) => {
err.log();
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Failed to scan duration"]
);
@ -837,20 +807,20 @@ impl MccParse {
Err(flow) => {
match flow {
gst::FlowError::Flushing => {
gst::debug!(CAT, obj: element, "Pausing after flow {:?}", flow);
gst::debug!(CAT, imp: self, "Pausing after flow {:?}", flow);
}
gst::FlowError::Eos => {
self.push_eos(element);
self.push_eos();
gst::debug!(CAT, obj: element, "Pausing after flow {:?}", flow);
gst::debug!(CAT, imp: self, "Pausing after flow {:?}", flow);
}
_ => {
self.push_eos(element);
self.push_eos();
gst::error!(CAT, obj: element, "Pausing after flow {:?}", flow);
gst::error!(CAT, imp: self, "Pausing after flow {:?}", flow);
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Failed,
["Streaming stopped, reason: {:?}", flow]
);
@ -865,12 +835,11 @@ impl MccParse {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::MccParse,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
self.handle_buffer(element, Some(buffer), false)
self.handle_buffer(Some(buffer), false)
}
fn flush(&self, mut state: MutexGuard<State>) -> MutexGuard<State> {
@ -893,7 +862,7 @@ impl MccParse {
self.state.lock().unwrap()
}
fn sink_event(&self, pad: &gst::Pad, element: &super::MccParse, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -914,14 +883,14 @@ impl MccParse {
let state = self.flush(state);
drop(state);
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::Eos(_) => {
gst::log!(CAT, obj: pad, "Draining");
if let Err(err) = self.handle_buffer(element, None, false) {
if let Err(err) = self.handle_buffer(None, false) {
gst::error!(CAT, obj: pad, "Failed to drain parser: {:?}", err);
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => {
if event.is_sticky()
@ -933,15 +902,15 @@ impl MccParse {
state.pending_events.push(event);
true
} else {
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
}
}
}
fn perform_seek(&self, event: &gst::event::Seek, element: &super::MccParse) -> bool {
fn perform_seek(&self, event: &gst::event::Seek) -> bool {
if self.state.lock().unwrap().pull.is_none() {
gst::error!(CAT, obj: element, "seeking is only supported in pull mode");
gst::error!(CAT, imp: self, "seeking is only supported in pull mode");
return false;
}
@ -950,7 +919,7 @@ impl MccParse {
let mut start: Option<gst::ClockTime> = match start.try_into() {
Ok(start) => start,
Err(_) => {
gst::error!(CAT, obj: element, "seek has invalid format");
gst::error!(CAT, imp: self, "seek has invalid format");
return false;
}
};
@ -958,18 +927,18 @@ impl MccParse {
let mut stop: Option<gst::ClockTime> = match stop.try_into() {
Ok(stop) => stop,
Err(_) => {
gst::error!(CAT, obj: element, "seek has invalid format");
gst::error!(CAT, imp: self, "seek has invalid format");
return false;
}
};
if !flags.contains(gst::SeekFlags::FLUSH) {
gst::error!(CAT, obj: element, "only flushing seeks are supported");
gst::error!(CAT, imp: self, "only flushing seeks are supported");
return false;
}
if start_type == gst::SeekType::End || stop_type == gst::SeekType::End {
gst::error!(CAT, obj: element, "Relative seeks are not supported");
gst::error!(CAT, imp: self, "Relative seeks are not supported");
return false;
}
@ -979,14 +948,14 @@ impl MccParse {
.seqnum(seek_seqnum)
.build();
gst::debug!(CAT, obj: element, "Sending event {:?} upstream", event);
gst::debug!(CAT, imp: self, "Sending event {:?} upstream", event);
self.sinkpad.push_event(event);
let event = gst::event::FlushStart::builder()
.seqnum(seek_seqnum)
.build();
gst::debug!(CAT, obj: element, "Pushing event {:?}", event);
gst::debug!(CAT, imp: self, "Pushing event {:?}", event);
self.srcpad.push_event(event);
let _ = self.sinkpad.pause_task();
@ -1014,7 +983,7 @@ impl MccParse {
/* Drop our state while we push a serialized event upstream */
drop(state);
gst::debug!(CAT, obj: element, "Sending event {:?} upstream", event);
gst::debug!(CAT, imp: self, "Sending event {:?} upstream", event);
self.sinkpad.push_event(event);
state = self.state.lock().unwrap();
@ -1023,7 +992,7 @@ impl MccParse {
.segment
.do_seek(rate, flags, start_type, start, stop_type, stop);
match self.start_task(element) {
match self.start_task() {
Err(error) => {
error.log();
false
@ -1032,22 +1001,17 @@ impl MccParse {
}
}
fn src_event(&self, pad: &gst::Pad, element: &super::MccParse, event: gst::Event) -> bool {
fn src_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() {
EventView::Seek(e) => self.perform_seek(e, element),
_ => pad.event_default(Some(element), event),
EventView::Seek(e) => self.perform_seek(e),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::MccParse,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
@ -1097,7 +1061,7 @@ impl MccParse {
self.sinkpad.peer_query(query)
}
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
}
@ -1114,29 +1078,34 @@ impl ObjectSubclass for MccParse {
.activate_function(|pad, parent| {
MccParse::catch_panic_pad_function(
parent,
|| Err(loggable_error!(CAT, "Panic activating sink pad")),
|parse, element| parse.sink_activate(pad, element),
|| Err(gst::loggable_error!(CAT, "Panic activating sink pad")),
|parse| parse.sink_activate(pad),
)
})
.activatemode_function(|pad, parent, mode, active| {
MccParse::catch_panic_pad_function(
parent,
|| Err(loggable_error!(CAT, "Panic activating sink pad with mode")),
|parse, element| parse.sink_activatemode(pad, element, mode, active),
|| {
Err(gst::loggable_error!(
CAT,
"Panic activating sink pad with mode"
))
},
|parse| parse.sink_activatemode(pad, mode, active),
)
})
.chain_function(|pad, parent, buffer| {
MccParse::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|parse, element| parse.sink_chain(pad, element, buffer),
|parse| parse.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
MccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.sink_event(pad, element, event),
|parse| parse.sink_event(pad, event),
)
})
.build();
@ -1147,14 +1116,14 @@ impl ObjectSubclass for MccParse {
MccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_event(pad, element, event),
|parse| parse.src_event(pad, event),
)
})
.query_function(|pad, parent, query| {
MccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_query(pad, element, query),
|parse| parse.src_query(pad, query),
)
})
.build();
@ -1168,9 +1137,10 @@ impl ObjectSubclass for MccParse {
}
impl ObjectImpl for MccParse {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -1241,10 +1211,9 @@ impl ElementImpl for MccParse {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused | gst::StateChange::PausedToReady => {
@ -1255,6 +1224,6 @@ impl ElementImpl for MccParse {
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -76,7 +76,7 @@ impl State {
fn generate_caption(
&mut self,
element: &super::SccEnc,
imp: &SccEnc,
buffer: gst::Buffer,
) -> Result<Option<gst::Buffer>, gst::FlowError> {
// Arbitrary number that was chosen to keep in order
@ -86,8 +86,8 @@ impl State {
assert!(self.internal_buffer.len() < MAXIMUM_PACKETES_PER_LINE);
if buffer.size() != 2 {
gst::element_error!(
element,
gst::element_imp_error!(
imp,
gst::StreamError::Format,
["Wrongly sized CEA608 packet: {}", buffer.size()]
);
@ -97,8 +97,8 @@ impl State {
if !self.settings.output_padding {
let map = buffer.map_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
imp,
gst::StreamError::Format,
["Failed to map buffer readable"]
);
@ -116,8 +116,8 @@ impl State {
let mut timecode = buffer
.meta::<gst_video::VideoTimeCodeMeta>()
.ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
imp,
gst::StreamError::Format,
["Stream with timecodes on each buffer required"]
);
@ -140,7 +140,7 @@ impl State {
// flush the previous line into the buffer, and push
// the new packet to the, now empty, internal buffer
if Some(&timecode) != self.expected_timecode.as_ref() {
let outbuf = self.write_line(element)?;
let outbuf = self.write_line(imp)?;
assert!(self.internal_buffer.is_empty());
self.internal_buffer.push(buffer);
@ -156,17 +156,14 @@ impl State {
self.internal_buffer.push(buffer);
if self.internal_buffer.len() == MAXIMUM_PACKETES_PER_LINE {
return self.write_line(element);
return self.write_line(imp);
}
Ok(None)
}
// Flush the internal buffers into a line
fn write_line(
&mut self,
element: &super::SccEnc,
) -> Result<Option<gst::Buffer>, gst::FlowError> {
fn write_line(&mut self, imp: &SccEnc) -> Result<Option<gst::Buffer>, gst::FlowError> {
let mut outbuf = Vec::new();
let mut line_start = true;
@ -181,8 +178,8 @@ impl State {
let first_buf = self.internal_buffer.first().unwrap();
for buffer in self.internal_buffer.iter() {
let map = buffer.map_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
imp,
gst::StreamError::Format,
["Failed to map buffer readable"]
);
@ -251,13 +248,12 @@ impl SccEnc {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::SccEnc,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
let mut state = self.state.lock().unwrap();
let res = state.generate_caption(element, buffer)?;
let res = state.generate_caption(self, buffer)?;
if let Some(outbuf) = res {
gst::trace!(CAT, obj: pad, "Pushing buffer {:?} to the pad", &outbuf);
@ -269,7 +265,7 @@ impl SccEnc {
Ok(gst::FlowSuccess::Ok)
}
fn sink_event(&self, pad: &gst::Pad, element: &super::SccEnc, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -297,7 +293,7 @@ impl SccEnc {
EventView::Eos(_) => {
let mut state = self.state.lock().unwrap();
let outbuf = state.write_line(element);
let outbuf = state.write_line(self);
if let Ok(Some(buffer)) = outbuf {
gst::trace!(CAT, obj: pad, "Pushing buffer {:?} to the pad", &buffer);
@ -311,13 +307,13 @@ impl SccEnc {
gst::error!(CAT, obj: pad, "Failed to write a line after EOS: {:?}", err);
return false;
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_event(&self, pad: &gst::Pad, element: &super::SccEnc, event: gst::Event) -> bool {
fn src_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -326,16 +322,11 @@ impl SccEnc {
gst::log!(CAT, obj: pad, "Dropping seek event");
false
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::SccEnc,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
@ -351,7 +342,7 @@ impl SccEnc {
);
true
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
}
@ -369,33 +360,21 @@ impl ObjectSubclass for SccEnc {
SccEnc::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|enc, element| enc.sink_chain(pad, element, buffer),
|enc| enc.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
SccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.sink_event(pad, element, event),
)
SccEnc::catch_panic_pad_function(parent, || false, |enc| enc.sink_event(pad, event))
})
.build();
let templ = klass.pad_template("src").unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
.event_function(|pad, parent, event| {
SccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_event(pad, element, event),
)
SccEnc::catch_panic_pad_function(parent, || false, |enc| enc.src_event(pad, event))
})
.query_function(|pad, parent, query| {
SccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_query(pad, element, query),
)
SccEnc::catch_panic_pad_function(parent, || false, |enc| enc.src_query(pad, query))
})
.build();
@ -409,9 +388,10 @@ impl ObjectSubclass for SccEnc {
}
impl ObjectImpl for SccEnc {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -433,13 +413,7 @@ impl ObjectImpl for SccEnc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"output-padding" => {
self.settings.lock().unwrap().output_padding =
@ -449,7 +423,7 @@ impl ObjectImpl for SccEnc {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"output-padding" => {
let settings = self.settings.lock().unwrap();
@ -509,10 +483,9 @@ impl ElementImpl for SccEnc {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused => {
@ -529,6 +502,6 @@ impl ElementImpl for SccEnc {
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -10,7 +10,6 @@
use gst::glib;
use gst::prelude::*;
use gst::subclass::prelude::*;
use gst::{element_error, loggable_error};
use std::cmp;
use std::sync::{Mutex, MutexGuard};
@ -38,10 +37,12 @@ struct PullState {
}
impl PullState {
fn new(element: &super::SccParse, pad: &gst::Pad) -> Self {
fn new(imp: &SccParse, pad: &gst::Pad) -> Self {
Self {
need_stream_start: true,
stream_id: pad.create_stream_id(element, Some("src")).to_string(),
stream_id: pad
.create_stream_id(&*imp.instance(), Some("src"))
.to_string(),
offset: 0,
duration: gst::ClockTime::NONE,
}
@ -142,7 +143,7 @@ impl State {
&mut self,
tc: &TimeCode,
framerate: gst::Fraction,
element: &super::SccParse,
imp: &SccParse,
) -> Result<gst_video::ValidVideoTimeCode, gst::FlowError> {
match parse_timecode(framerate, tc) {
Ok(timecode) => Ok(timecode),
@ -152,8 +153,8 @@ impl State {
.as_ref()
.map(Clone::clone)
.ok_or_else(|| {
element_error!(
element,
gst::element_imp_error!(
imp,
gst::StreamError::Decode,
["Invalid first timecode {:?}", err]
);
@ -163,7 +164,7 @@ impl State {
gst::warning!(
CAT,
obj: element,
imp: imp,
"Invalid timecode {:?}, using previous {:?}",
err,
last_timecode
@ -176,11 +177,7 @@ impl State {
/// Calculate a timestamp from the timecode and make sure to
/// not produce timestamps jumping backwards
fn update_timestamp(
&mut self,
timecode: &gst_video::ValidVideoTimeCode,
element: &super::SccParse,
) {
fn update_timestamp(&mut self, timecode: &gst_video::ValidVideoTimeCode, imp: &SccParse) {
let nsecs = timecode.time_since_daily_jam();
if self
@ -191,7 +188,7 @@ impl State {
} else {
gst::fixme!(
CAT,
obj: element,
imp: imp,
"New position {} < last position {}",
nsecs,
self.last_position.display(),
@ -204,12 +201,12 @@ impl State {
buffer: &mut gst::buffer::Buffer,
timecode: &gst_video::ValidVideoTimeCode,
framerate: gst::Fraction,
element: &super::SccParse,
imp: &SccParse,
) {
let buffer = buffer.get_mut().unwrap();
gst_video::VideoTimeCodeMeta::add(buffer, timecode);
self.update_timestamp(timecode, element);
self.update_timestamp(timecode, imp);
buffer.set_pts(self.last_position);
buffer.set_duration(
@ -219,7 +216,7 @@ impl State {
fn create_events(
&mut self,
element: &super::SccParse,
imp: &SccParse,
framerate: Option<gst::Fraction>,
) -> Vec<gst::Event> {
let mut events = Vec::new();
@ -253,7 +250,7 @@ impl State {
self.framerate = Some(framerate);
events.push(gst::event::Caps::new(&caps));
gst::info!(CAT, obj: element, "Caps changed to {:?}", &caps);
gst::info!(CAT, imp: imp, "Caps changed to {:?}", &caps);
}
}
@ -282,15 +279,14 @@ pub struct SccParse {
impl SccParse {
fn handle_buffer(
&self,
element: &super::SccParse,
buffer: Option<gst::Buffer>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state = self.state.lock().unwrap();
let drain = if let Some(buffer) = buffer {
let buffer = buffer.into_mapped_buffer_readable().map_err(|_| {
element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to map buffer readable"]
);
@ -308,14 +304,14 @@ impl SccParse {
let line = state.line(drain);
match line {
Ok(Some(SccLine::Caption(tc, data))) => {
state = self.handle_line(tc, data, element, state)?;
state = self.handle_line(tc, data, state)?;
}
Ok(Some(line)) => {
gst::debug!(CAT, obj: element, "Got line '{:?}'", line);
gst::debug!(CAT, imp: self, "Got line '{:?}'", line);
}
Err((line, err)) => {
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Couldn't parse line '{:?}': {:?}", line, err]
);
@ -336,12 +332,11 @@ impl SccParse {
&self,
tc: TimeCode,
data: Vec<u8>,
element: &super::SccParse,
mut state: MutexGuard<State>,
) -> Result<MutexGuard<State>, gst::FlowError> {
gst::trace!(
CAT,
obj: element,
imp: self,
"Got caption buffer with timecode {:?} and size {}",
tc,
data.len()
@ -355,7 +350,7 @@ impl SccParse {
gst::Fraction::new(30, 1)
};
let mut timecode = state.handle_timecode(&tc, framerate, element)?;
let mut timecode = state.handle_timecode(&tc, framerate, self)?;
let start_time = timecode.time_since_daily_jam();
let segment_start = state.segment.start();
let clip_buffers = if state.seeking {
@ -369,7 +364,7 @@ impl SccParse {
gst::trace!(
CAT,
obj: element,
imp: self,
"Checking inside of segment, line start {} line stop {} segment start {} num bufs {}",
start_time,
stop_time,
@ -408,18 +403,13 @@ impl SccParse {
buf_mut.copy_from_slice(0, d).unwrap();
}
state.add_buffer_metadata(&mut buffer, &timecode, framerate, element);
state.add_buffer_metadata(&mut buffer, &timecode, framerate, self);
timecode.increment_frame();
if clip_buffers {
let end_time = buffer.pts().opt_add(buffer.duration());
if end_time.opt_lt(segment_start).unwrap_or(false) {
gst::trace!(
CAT,
obj: element,
"Skip segment clipped buffer {:?}",
buffer,
);
gst::trace!(CAT, imp: self, "Skip segment clipped buffer {:?}", buffer,);
continue;
}
@ -443,19 +433,19 @@ impl SccParse {
// Update the last_timecode to the current one
state.last_timecode = Some(timecode);
let events = state.create_events(element, Some(framerate));
let events = state.create_events(self, Some(framerate));
// Drop our state mutex while we push out buffers or events
drop(state);
for event in events {
gst::debug!(CAT, obj: element, "Pushing event {:?}", event);
gst::debug!(CAT, imp: self, "Pushing event {:?}", event);
self.srcpad.push_event(event);
}
self.srcpad.push_list(buffers).map_err(|err| {
if err != gst::FlowError::Flushing && err != gst::FlowError::Eos {
gst::error!(CAT, obj: element, "Pushing buffer returned {:?}", err);
gst::error!(CAT, imp: self, "Pushing buffer returned {:?}", err);
}
err
})?;
@ -467,11 +457,7 @@ impl SccParse {
Ok(self.state.lock().unwrap())
}
fn sink_activate(
&self,
pad: &gst::Pad,
element: &super::SccParse,
) -> Result<(), gst::LoggableError> {
fn sink_activate(&self, pad: &gst::Pad) -> Result<(), gst::LoggableError> {
let mode = {
let mut query = gst::query::Scheduling::new();
let mut state = self.state.lock().unwrap();
@ -486,7 +472,7 @@ impl SccParse {
{
gst::debug!(CAT, obj: pad, "Activating in Pull mode");
state.pull = Some(PullState::new(element, &self.srcpad));
state.pull = Some(PullState::new(self, &self.srcpad));
gst::PadMode::Pull
} else {
@ -499,25 +485,13 @@ impl SccParse {
Ok(())
}
fn start_task(&self, element: &super::SccParse) -> Result<(), gst::LoggableError> {
let element_weak = element.downgrade();
let pad_weak = self.sinkpad.downgrade();
fn start_task(&self) -> Result<(), gst::LoggableError> {
let imp = self.ref_counted();
let res = self.sinkpad.start_task(move || {
let element = match element_weak.upgrade() {
Some(element) => element,
None => {
if let Some(pad) = pad_weak.upgrade() {
let _ = pad.pause_task();
}
return;
}
};
let parse = element.imp();
parse.loop_fn(&element);
imp.loop_fn();
});
if res.is_err() {
return Err(loggable_error!(CAT, "Failed to start pad task"));
return Err(gst::loggable_error!(CAT, "Failed to start pad task"));
}
Ok(())
}
@ -525,13 +499,12 @@ impl SccParse {
fn sink_activatemode(
&self,
_pad: &gst::Pad,
element: &super::SccParse,
mode: gst::PadMode,
active: bool,
) -> Result<(), gst::LoggableError> {
if mode == gst::PadMode::Pull {
if active {
self.start_task(element)?;
self.start_task()?;
} else {
let _ = self.sinkpad.stop_task();
}
@ -540,23 +513,26 @@ impl SccParse {
Ok(())
}
fn scan_duration(
&self,
element: &super::SccParse,
) -> Result<Option<gst_video::ValidVideoTimeCode>, gst::LoggableError> {
gst::debug!(CAT, obj: element, "Scanning duration");
fn scan_duration(&self) -> Result<Option<gst_video::ValidVideoTimeCode>, gst::LoggableError> {
gst::debug!(CAT, imp: self, "Scanning duration");
/* First let's query the bytes duration upstream */
let mut q = gst::query::Duration::new(gst::Format::Bytes);
if !self.sinkpad.peer_query(&mut q) {
return Err(loggable_error!(CAT, "Failed to query upstream duration"));
return Err(gst::loggable_error!(
CAT,
"Failed to query upstream duration"
));
}
let size = match q.result().try_into().unwrap() {
Some(gst::format::Bytes(size)) => size,
None => {
return Err(loggable_error!(CAT, "Failed to query upstream duration"));
return Err(gst::loggable_error!(
CAT,
"Failed to query upstream duration"
));
}
};
@ -574,7 +550,7 @@ impl SccParse {
buffers.push(buffer);
}
Err(flow) => {
return Err(loggable_error!(
return Err(gst::loggable_error!(
CAT,
"Failed to pull buffer while scanning duration: {:?}",
flow
@ -589,7 +565,7 @@ impl SccParse {
let buf = buf
.clone()
.into_mapped_buffer_readable()
.map_err(|_| loggable_error!(CAT, "Failed to map buffer readable"))?;
.map_err(|_| gst::loggable_error!(CAT, "Failed to map buffer readable"))?;
reader.push(buf);
}
@ -613,25 +589,20 @@ impl SccParse {
}
if last_tc.is_some() || offset == 0 {
gst::debug!(
CAT,
obj: element,
"Duration scan done, last_tc: {:?}",
last_tc
);
gst::debug!(CAT, imp: self, "Duration scan done, last_tc: {:?}", last_tc);
break (Ok(last_tc));
}
}
}
fn push_eos(&self, element: &super::SccParse) {
fn push_eos(&self) {
let mut state = self.state.lock().unwrap();
if state.seeking {
state.need_flush_stop = true;
}
let mut events = state.create_events(element, None);
let mut events = state.create_events(self, None);
let mut eos_event = gst::event::Eos::builder();
if let Some(seek_seqnum) = state.seek_seqnum {
@ -644,12 +615,12 @@ impl SccParse {
drop(state);
for event in events {
gst::debug!(CAT, obj: element, "Pushing event {:?}", event);
gst::debug!(CAT, imp: self, "Pushing event {:?}", event);
self.srcpad.push_event(event);
}
}
fn loop_fn(&self, element: &super::SccParse) {
fn loop_fn(&self) {
let mut state = self.state.lock().unwrap();
let State {
ref framerate,
@ -676,8 +647,8 @@ impl SccParse {
Err(flow) => {
gst::error!(CAT, obj: &self.sinkpad, "Failed to pull, reason: {:?}", flow);
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Failed,
["Streaming stopped, failed to pull buffer"]
);
@ -687,10 +658,10 @@ impl SccParse {
}
};
match self.handle_buffer(element, buffer) {
match self.handle_buffer(buffer) {
Ok(_) => {
if scan_duration {
match self.scan_duration(element) {
match self.scan_duration() {
Ok(Some(tc)) => {
let mut state = self.state.lock().unwrap();
let mut pull = state.pull.as_mut().unwrap();
@ -704,8 +675,8 @@ impl SccParse {
Err(err) => {
err.log();
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Decode,
["Failed to scan duration"]
);
@ -718,20 +689,20 @@ impl SccParse {
Err(flow) => {
match flow {
gst::FlowError::Flushing => {
gst::debug!(CAT, obj: element, "Pausing after flow {:?}", flow);
gst::debug!(CAT, imp: self, "Pausing after flow {:?}", flow);
}
gst::FlowError::Eos => {
self.push_eos(element);
self.push_eos();
gst::debug!(CAT, obj: element, "Pausing after flow {:?}", flow);
gst::debug!(CAT, imp: self, "Pausing after flow {:?}", flow);
}
_ => {
self.push_eos(element);
self.push_eos();
gst::error!(CAT, obj: element, "Pausing after flow {:?}", flow);
gst::error!(CAT, imp: self, "Pausing after flow {:?}", flow);
element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Failed,
["Streaming stopped, reason: {:?}", flow]
);
@ -746,12 +717,11 @@ impl SccParse {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::SccParse,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
self.handle_buffer(element, Some(buffer))
self.handle_buffer(Some(buffer))
}
fn flush(&self, mut state: MutexGuard<State>) -> MutexGuard<State> {
@ -771,7 +741,7 @@ impl SccParse {
self.state.lock().unwrap()
}
fn sink_event(&self, pad: &gst::Pad, element: &super::SccParse, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -792,14 +762,14 @@ impl SccParse {
let state = self.flush(state);
drop(state);
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::Eos(_) => {
gst::log!(CAT, obj: pad, "Draining");
if let Err(err) = self.handle_buffer(element, None) {
if let Err(err) = self.handle_buffer(None) {
gst::error!(CAT, obj: pad, "Failed to drain parser: {:?}", err);
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => {
if event.is_sticky()
@ -811,15 +781,15 @@ impl SccParse {
state.pending_events.push(event);
true
} else {
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
}
}
}
fn perform_seek(&self, event: &gst::event::Seek, element: &super::SccParse) -> bool {
fn perform_seek(&self, event: &gst::event::Seek) -> bool {
if self.state.lock().unwrap().pull.is_none() {
gst::error!(CAT, obj: element, "seeking is only supported in pull mode");
gst::error!(CAT, imp: self, "seeking is only supported in pull mode");
return false;
}
@ -828,7 +798,7 @@ impl SccParse {
let mut start: Option<gst::ClockTime> = match start.try_into() {
Ok(start) => start,
Err(_) => {
gst::error!(CAT, obj: element, "seek has invalid format");
gst::error!(CAT, imp: self, "seek has invalid format");
return false;
}
};
@ -836,18 +806,18 @@ impl SccParse {
let mut stop: Option<gst::ClockTime> = match stop.try_into() {
Ok(stop) => stop,
Err(_) => {
gst::error!(CAT, obj: element, "seek has invalid format");
gst::error!(CAT, imp: self, "seek has invalid format");
return false;
}
};
if !flags.contains(gst::SeekFlags::FLUSH) {
gst::error!(CAT, obj: element, "only flushing seeks are supported");
gst::error!(CAT, imp: self, "only flushing seeks are supported");
return false;
}
if start_type == gst::SeekType::End || stop_type == gst::SeekType::End {
gst::error!(CAT, obj: element, "Relative seeks are not supported");
gst::error!(CAT, imp: self, "Relative seeks are not supported");
return false;
}
@ -857,14 +827,14 @@ impl SccParse {
.seqnum(seek_seqnum)
.build();
gst::debug!(CAT, obj: element, "Sending event {:?} upstream", event);
gst::debug!(CAT, imp: self, "Sending event {:?} upstream", event);
self.sinkpad.push_event(event);
let event = gst::event::FlushStart::builder()
.seqnum(seek_seqnum)
.build();
gst::debug!(CAT, obj: element, "Pushing event {:?}", event);
gst::debug!(CAT, imp: self, "Pushing event {:?}", event);
self.srcpad.push_event(event);
let _ = self.sinkpad.pause_task();
@ -892,7 +862,7 @@ impl SccParse {
/* Drop our state while we push a serialized event upstream */
drop(state);
gst::debug!(CAT, obj: element, "Sending event {:?} upstream", event);
gst::debug!(CAT, imp: self, "Sending event {:?} upstream", event);
self.sinkpad.push_event(event);
state = self.state.lock().unwrap();
@ -901,7 +871,7 @@ impl SccParse {
.segment
.do_seek(rate, flags, start_type, start, stop_type, stop);
match self.start_task(element) {
match self.start_task() {
Err(error) => {
error.log();
false
@ -910,22 +880,17 @@ impl SccParse {
}
}
fn src_event(&self, pad: &gst::Pad, element: &super::SccParse, event: gst::Event) -> bool {
fn src_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() {
EventView::Seek(e) => self.perform_seek(e, element),
_ => pad.event_default(Some(element), event),
EventView::Seek(e) => self.perform_seek(e),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::SccParse,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
@ -975,7 +940,7 @@ impl SccParse {
self.sinkpad.peer_query(query)
}
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
}
@ -992,29 +957,34 @@ impl ObjectSubclass for SccParse {
.activate_function(|pad, parent| {
SccParse::catch_panic_pad_function(
parent,
|| Err(loggable_error!(CAT, "Panic activating sink pad")),
|parse, element| parse.sink_activate(pad, element),
|| Err(gst::loggable_error!(CAT, "Panic activating sink pad")),
|parse| parse.sink_activate(pad),
)
})
.activatemode_function(|pad, parent, mode, active| {
SccParse::catch_panic_pad_function(
parent,
|| Err(loggable_error!(CAT, "Panic activating sink pad with mode")),
|parse, element| parse.sink_activatemode(pad, element, mode, active),
|| {
Err(gst::loggable_error!(
CAT,
"Panic activating sink pad with mode"
))
},
|parse| parse.sink_activatemode(pad, mode, active),
)
})
.chain_function(|pad, parent, buffer| {
SccParse::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|parse, element| parse.sink_chain(pad, element, buffer),
|parse| parse.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
SccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.sink_event(pad, element, event),
|parse| parse.sink_event(pad, event),
)
})
.build();
@ -1025,14 +995,14 @@ impl ObjectSubclass for SccParse {
SccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_event(pad, element, event),
|parse| parse.src_event(pad, event),
)
})
.query_function(|pad, parent, query| {
SccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_query(pad, element, query),
|parse| parse.src_query(pad, query),
)
})
.build();
@ -1046,9 +1016,10 @@ impl ObjectSubclass for SccParse {
}
impl ObjectImpl for SccParse {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -1104,10 +1075,9 @@ impl ElementImpl for SccParse {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused | gst::StateChange::PausedToReady => {
@ -1118,6 +1088,6 @@ impl ElementImpl for SccParse {
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}

View file

@ -85,12 +85,8 @@ pub struct TranscriberBin {
}
impl TranscriberBin {
fn construct_transcription_bin(
&self,
element: &super::TranscriberBin,
state: &mut State,
) -> Result<(), Error> {
gst::debug!(CAT, obj: element, "Building transcription bin");
fn construct_transcription_bin(&self, state: &mut State) -> Result<(), Error> {
gst::debug!(CAT, imp: self, "Building transcription bin");
let aqueue_transcription = gst::ElementFactory::make("queue", Some("transqueue"))?;
aqueue_transcription.set_property("max-size-buffers", 0u32);
@ -153,11 +149,7 @@ impl TranscriberBin {
Ok(())
}
fn construct_internal_bin(
&self,
element: &super::TranscriberBin,
state: &mut State,
) -> Result<(), Error> {
fn construct_internal_bin(&self, state: &mut State) -> Result<(), Error> {
let aclocksync = gst::ElementFactory::make("clocksync", None)?;
let vclocksync = gst::ElementFactory::make("clocksync", None)?;
@ -202,17 +194,16 @@ impl TranscriberBin {
state.internal_bin.add_pad(&internal_video_sinkpad)?;
state.internal_bin.add_pad(&internal_video_srcpad)?;
let element_weak = element.downgrade();
let imp_weak = self.downgrade();
let comp_sinkpad = &state.cccombiner.static_pad("sink").unwrap();
// Drop caption meta from video buffer if user preference is transcription
comp_sinkpad.add_probe(gst::PadProbeType::BUFFER, move |_, probe_info| {
let element = match element_weak.upgrade() {
let imp = match imp_weak.upgrade() {
None => return gst::PadProbeReturn::Remove,
Some(element) => element,
Some(imp) => imp,
};
let trans = TranscriberBin::from_instance(&element);
let settings = trans.settings.lock().unwrap();
let settings = imp.settings.lock().unwrap();
if settings.caption_source != CaptionSource::Transcription {
return gst::PadProbeReturn::Pass;
}
@ -227,7 +218,7 @@ impl TranscriberBin {
gst::PadProbeReturn::Ok
});
element.add(&state.internal_bin)?;
self.instance().add(&state.internal_bin)?;
state
.cccombiner
@ -242,12 +233,12 @@ impl TranscriberBin {
self.video_srcpad
.set_target(Some(&state.internal_bin.static_pad("video_src").unwrap()))?;
self.construct_transcription_bin(element, state)?;
self.construct_transcription_bin(state)?;
Ok(())
}
fn setup_transcription(&self, element: &super::TranscriberBin, state: &State) {
fn setup_transcription(&self, state: &State) {
let settings = self.settings.lock().unwrap();
let mut cc_caps = settings.cc_caps.clone();
@ -285,10 +276,10 @@ impl TranscriberBin {
drop(settings);
self.setup_cc_mode(element, state);
self.setup_cc_mode(state);
}
fn disable_transcription_bin(&self, element: &super::TranscriberBin) {
fn disable_transcription_bin(&self) {
let mut state = self.state.lock().unwrap();
if let Some(ref mut state) = state.as_mut() {
@ -299,7 +290,7 @@ impl TranscriberBin {
let passthrough = self.settings.lock().unwrap().passthrough;
if passthrough {
gst::debug!(CAT, obj: element, "disabling transcription bin");
gst::debug!(CAT, imp: self, "disabling transcription bin");
let bin_sink_pad = state.transcription_bin.static_pad("sink").unwrap();
if let Some(audio_tee_pad) = bin_sink_pad.peer() {
@ -319,13 +310,13 @@ impl TranscriberBin {
}
}
fn block_and_update(&self, element: &super::TranscriberBin, passthrough: bool) {
fn block_and_update(&self, passthrough: bool) {
let mut s = self.state.lock().unwrap();
if let Some(ref mut state) = s.as_mut() {
if passthrough {
let sinkpad = state.transcription_bin.static_pad("sink").unwrap();
let element_weak = element.downgrade();
let imp_weak = self.downgrade();
state.tearing_down = true;
drop(s);
let _ = sinkpad.add_probe(
@ -333,14 +324,12 @@ impl TranscriberBin {
| gst::PadProbeType::BUFFER
| gst::PadProbeType::EVENT_DOWNSTREAM,
move |_pad, _info| {
let element = match element_weak.upgrade() {
let imp = match imp_weak.upgrade() {
None => return gst::PadProbeReturn::Pass,
Some(element) => element,
Some(imp) => imp,
};
let this = element.imp();
this.disable_transcription_bin(&element);
imp.disable_transcription_bin();
gst::PadProbeReturn::Remove
},
@ -363,10 +352,10 @@ impl TranscriberBin {
}
}
fn setup_cc_mode(&self, element: &super::TranscriberBin, state: &State) {
fn setup_cc_mode(&self, state: &State) {
let mode = self.settings.lock().unwrap().mode;
gst::debug!(CAT, obj: element, "setting CC mode {:?}", mode);
gst::debug!(CAT, imp: self, "setting CC mode {:?}", mode);
state.tttocea608.set_property("mode", mode);
@ -386,12 +375,11 @@ impl TranscriberBin {
fn relink_transcriber(
&self,
state: &mut State,
element: &super::TranscriberBin,
old_transcriber: &gst::Element,
) -> Result<(), Error> {
gst::error!(
CAT,
obj: element,
imp: self,
"Relinking transcriber, old: {:?}, new: {:?}",
old_transcriber,
state.transcriber
@ -414,12 +402,7 @@ impl TranscriberBin {
}
#[allow(clippy::single_match)]
fn src_query(
&self,
pad: &gst::Pad,
element: &super::TranscriberBin,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
gst::log!(CAT, obj: pad, "Handling query {:?}", query);
@ -428,7 +411,7 @@ impl TranscriberBin {
QueryViewMut::Latency(q) => {
let mut upstream_query = gst::query::Latency::new();
let ret = pad.query_default(Some(element), &mut upstream_query);
let ret = pad.query_default(Some(&*self.instance()), &mut upstream_query);
if ret {
let (_, mut min, _) = upstream_query.result();
@ -453,7 +436,7 @@ impl TranscriberBin {
ret
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
@ -497,12 +480,7 @@ impl TranscriberBin {
}
#[allow(clippy::single_match)]
fn video_sink_event(
&self,
pad: &gst::Pad,
element: &super::TranscriberBin,
event: gst::Event,
) -> bool {
fn video_sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -525,16 +503,16 @@ impl TranscriberBin {
if !had_framerate {
gst::info!(
CAT,
obj: element,
imp: self,
"Received video caps, setting up transcription"
);
self.setup_transcription(element, state);
self.setup_transcription(state);
}
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
}
@ -554,7 +532,7 @@ impl ObjectSubclass for TranscriberBin {
TranscriberBin::catch_panic_pad_function(
parent,
|| false,
|transcriber, element| transcriber.src_query(pad.upcast_ref(), element, query),
|transcriber| transcriber.src_query(pad.upcast_ref(), query),
)
})
.build();
@ -565,9 +543,7 @@ impl ObjectSubclass for TranscriberBin {
TranscriberBin::catch_panic_pad_function(
parent,
|| false,
|transcriber, element| {
transcriber.video_sink_event(pad.upcast_ref(), element, event)
},
|transcriber| transcriber.video_sink_event(pad.upcast_ref(), event),
)
})
.build();
@ -577,7 +553,7 @@ impl ObjectSubclass for TranscriberBin {
TranscriberBin::catch_panic_pad_function(
parent,
|| false,
|transcriber, element| transcriber.src_query(pad.upcast_ref(), element, query),
|transcriber| transcriber.src_query(pad.upcast_ref(), query),
)
})
.build();
@ -644,13 +620,7 @@ impl ObjectImpl for TranscriberBin {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"passthrough" => {
let mut settings = self.settings.lock().unwrap();
@ -661,7 +631,7 @@ impl ObjectImpl for TranscriberBin {
if old_passthrough != new_passthrough {
drop(settings);
self.block_and_update(obj, new_passthrough);
self.block_and_update(new_passthrough);
}
}
"latency" => {
@ -685,7 +655,7 @@ impl ObjectImpl for TranscriberBin {
if old_mode != new_mode {
drop(settings);
self.setup_cc_mode(obj, self.state.lock().unwrap().as_ref().unwrap());
self.setup_cc_mode(self.state.lock().unwrap().as_ref().unwrap());
}
}
"cc-caps" => {
@ -698,7 +668,7 @@ impl ObjectImpl for TranscriberBin {
let old_transcriber = state.transcriber.clone();
state.transcriber = value.get().expect("type checked upstream");
if old_transcriber != state.transcriber {
match self.relink_transcriber(state, obj, &old_transcriber) {
match self.relink_transcriber(state, &old_transcriber) {
Ok(()) => (),
Err(err) => {
gst::error!(CAT, "invalid transcriber: {}", err);
@ -716,10 +686,10 @@ impl ObjectImpl for TranscriberBin {
let s = self.state.lock().unwrap();
if let Some(state) = s.as_ref() {
if settings.caption_source == CaptionSource::Inband {
gst::debug!(CAT, obj: obj, "Use inband caption, dropping transcription");
gst::debug!(CAT, imp: self, "Use inband caption, dropping transcription");
state.transcription_valve.set_property("drop", true);
} else {
gst::debug!(CAT, obj: obj, "Stop dropping transcription");
gst::debug!(CAT, imp: self, "Stop dropping transcription");
state.transcription_valve.set_property("drop", false);
}
}
@ -728,7 +698,7 @@ impl ObjectImpl for TranscriberBin {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"passthrough" => {
let settings = self.settings.lock().unwrap();
@ -767,16 +737,17 @@ impl ObjectImpl for TranscriberBin {
}
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.audio_srcpad).unwrap();
obj.add_pad(&self.audio_sinkpad).unwrap();
obj.add_pad(&self.video_srcpad).unwrap();
obj.add_pad(&self.video_sinkpad).unwrap();
*self.state.lock().unwrap() = match self.build_state() {
Ok(mut state) => match self.construct_internal_bin(obj, &mut state) {
Ok(mut state) => match self.construct_internal_bin(&mut state) {
Ok(()) => Some(state),
Err(err) => {
gst::error!(CAT, "Failed to build internal bin: {}", err);
@ -855,10 +826,9 @@ impl ElementImpl for TranscriberBin {
#[allow(clippy::single_match)]
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused => {
@ -868,14 +838,14 @@ impl ElementImpl for TranscriberBin {
if state.framerate.is_some() {
gst::info!(
CAT,
obj: element,
imp: self,
"Received video caps, setting up transcription"
);
self.setup_transcription(element, state);
self.setup_transcription(state);
}
} else {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Failed,
["Can't change state with no state"]
);
@ -885,12 +855,12 @@ impl ElementImpl for TranscriberBin {
_ => (),
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}
impl BinImpl for TranscriberBin {
fn handle_message(&self, bin: &Self::Type, msg: gst::Message) {
fn handle_message(&self, msg: gst::Message) {
use gst::MessageView;
match msg.view() {
@ -902,7 +872,7 @@ impl BinImpl for TranscriberBin {
if msg.src().as_ref() == Some(state.transcriber.upcast_ref()) {
gst::error!(
CAT,
obj: bin,
imp: self,
"Transcriber has posted an error ({:?}), going back to passthrough",
m
);
@ -910,21 +880,21 @@ impl BinImpl for TranscriberBin {
let mut settings = self.settings.lock().unwrap();
settings.passthrough = true;
drop(settings);
bin.notify("passthrough");
bin.call_async(move |bin| {
self.instance().notify("passthrough");
self.instance().call_async(move |bin| {
let thiz = bin.imp();
thiz.block_and_update(bin, true);
thiz.block_and_update(true);
});
} else {
drop(s);
self.parent_handle_message(bin, msg);
self.parent_handle_message(msg);
}
} else {
drop(s);
self.parent_handle_message(bin, msg);
self.parent_handle_message(msg);
}
}
_ => self.parent_handle_message(bin, msg),
_ => self.parent_handle_message(msg),
}
}
}

View file

@ -151,7 +151,7 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
static SPACE: Lazy<u16> = Lazy::new(|| eia608_from_utf8_1(&[0x20, 0, 0, 0, 0]));
fn cc_data_buffer(
element: &super::TtToCea608,
imp: &TtToCea608,
cc_data: u16,
pts: gst::ClockTime,
duration: gst::ClockTime,
@ -163,14 +163,14 @@ fn cc_data_buffer(
if cc_data != 0x8080 {
gst::log!(
CAT,
obj: element,
imp: imp,
"{} -> {}: {}",
pts,
pts + duration,
eia608_to_text(cc_data)
);
} else {
gst::trace!(CAT, obj: element, "{} -> {}: padding", pts, pts + duration);
gst::trace!(CAT, imp: imp, "{} -> {}: padding", pts, pts + duration);
}
buf_mut.copy_from_slice(0, &data).unwrap();
@ -183,7 +183,7 @@ fn cc_data_buffer(
impl State {
fn check_erase_display(
&mut self,
element: &super::TtToCea608,
imp: &TtToCea608,
bufferlist: &mut gst::BufferListRef,
) -> bool {
if let Some(erase_display_frame_no) = self.erase_display_frame_no {
@ -191,7 +191,7 @@ impl State {
self.erase_display_frame_no = None;
self.column = 0;
self.send_roll_up_preamble = true;
self.erase_display_memory(element, bufferlist);
self.erase_display_memory(imp, bufferlist);
return true;
}
}
@ -199,13 +199,8 @@ impl State {
false
}
fn cc_data(
&mut self,
element: &super::TtToCea608,
bufferlist: &mut gst::BufferListRef,
cc_data: u16,
) {
self.check_erase_display(element, bufferlist);
fn cc_data(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef, cc_data: u16) {
self.check_erase_display(imp, bufferlist);
let (fps_n, fps_d) = (self.framerate.numer() as u64, self.framerate.denom() as u64);
@ -216,7 +211,7 @@ impl State {
if self.last_frame_no < self.max_frame_no {
self.last_frame_no += 1;
} else {
gst::debug!(CAT, obj: element, "More text than bandwidth!");
gst::debug!(CAT, imp: imp, "More text than bandwidth!");
}
let next_pts = (self.last_frame_no * gst::ClockTime::SECOND)
@ -225,122 +220,96 @@ impl State {
let duration = next_pts - pts;
bufferlist.insert(-1, cc_data_buffer(element, cc_data, pts, duration));
bufferlist.insert(-1, cc_data_buffer(imp, cc_data, pts, duration));
}
fn pad(
&mut self,
element: &super::TtToCea608,
bufferlist: &mut gst::BufferListRef,
frame_no: u64,
) {
fn pad(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef, frame_no: u64) {
while self.last_frame_no < frame_no {
if !self.check_erase_display(element, bufferlist) {
self.cc_data(element, bufferlist, 0x8080);
if !self.check_erase_display(imp, bufferlist) {
self.cc_data(imp, bufferlist, 0x8080);
}
}
}
fn resume_caption_loading(
&mut self,
element: &super::TtToCea608,
bufferlist: &mut gst::BufferListRef,
) {
fn resume_caption_loading(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef) {
self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_control_resume_caption_loading),
)
}
fn resume_direct_captioning(
&mut self,
element: &super::TtToCea608,
bufferlist: &mut gst::BufferListRef,
) {
fn resume_direct_captioning(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef) {
self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_control_resume_direct_captioning),
)
}
fn delete_to_end_of_row(
&mut self,
element: &super::TtToCea608,
bufferlist: &mut gst::BufferListRef,
) {
fn delete_to_end_of_row(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef) {
self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_control_delete_to_end_of_row),
)
}
fn roll_up_2(&mut self, element: &super::TtToCea608, bufferlist: &mut gst::BufferListRef) {
fn roll_up_2(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef) {
self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_control_roll_up_2),
)
}
fn roll_up_3(&mut self, element: &super::TtToCea608, bufferlist: &mut gst::BufferListRef) {
fn roll_up_3(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef) {
self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_control_roll_up_3),
)
}
fn roll_up_4(&mut self, element: &super::TtToCea608, bufferlist: &mut gst::BufferListRef) {
fn roll_up_4(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef) {
self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_control_roll_up_4),
)
}
fn carriage_return(
&mut self,
element: &super::TtToCea608,
bufferlist: &mut gst::BufferListRef,
) {
fn carriage_return(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef) {
self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_control_carriage_return),
)
}
fn end_of_caption(&mut self, element: &super::TtToCea608, bufferlist: &mut gst::BufferListRef) {
fn end_of_caption(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef) {
self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_control_end_of_caption),
)
}
fn tab_offset(
&mut self,
element: &super::TtToCea608,
bufferlist: &mut gst::BufferListRef,
offset: u32,
) {
fn tab_offset(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef, offset: u32) {
match offset {
0 => (),
1 => self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_tab_offset_1),
),
2 => self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_tab_offset_2),
),
3 => self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_tab_offset_3),
),
@ -350,14 +319,14 @@ impl State {
fn preamble_indent(
&mut self,
element: &super::TtToCea608,
imp: &TtToCea608,
bufferlist: &mut gst::BufferListRef,
row: i32,
col: i32,
underline: bool,
) {
self.cc_data(
element,
imp,
bufferlist,
eia608_row_column_preamble(row, col, underline),
)
@ -365,14 +334,14 @@ impl State {
fn preamble_style(
&mut self,
element: &super::TtToCea608,
imp: &TtToCea608,
bufferlist: &mut gst::BufferListRef,
row: i32,
style: u32,
underline: bool,
) {
self.cc_data(
element,
imp,
bufferlist,
eia608_row_style_preamble(row, style, underline),
)
@ -380,31 +349,21 @@ impl State {
fn midrow_change(
&mut self,
element: &super::TtToCea608,
imp: &TtToCea608,
bufferlist: &mut gst::BufferListRef,
style: u32,
underline: bool,
) {
self.cc_data(element, bufferlist, eia608_midrow_change(style, underline))
self.cc_data(imp, bufferlist, eia608_midrow_change(style, underline))
}
fn bna(
&mut self,
element: &super::TtToCea608,
bufferlist: &mut gst::BufferListRef,
bna1: u16,
bna2: u16,
) {
self.cc_data(element, bufferlist, eia608_from_basicna(bna1, bna2))
fn bna(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef, bna1: u16, bna2: u16) {
self.cc_data(imp, bufferlist, eia608_from_basicna(bna1, bna2))
}
fn erase_display_memory(
&mut self,
element: &super::TtToCea608,
bufferlist: &mut gst::BufferListRef,
) {
fn erase_display_memory(&mut self, imp: &TtToCea608, bufferlist: &mut gst::BufferListRef) {
self.cc_data(
element,
imp,
bufferlist,
eia608_control_command(ffi::eia608_control_t_eia608_control_erase_display_memory),
)
@ -423,14 +382,13 @@ pub struct TtToCea608 {
impl TtToCea608 {
fn open_chunk(
&self,
element: &super::TtToCea608,
state: &mut State,
chunk: &Chunk,
bufferlist: &mut gst::BufferListRef,
col: u32,
) -> bool {
if (chunk.style != state.style || chunk.underline != state.underline) && col < 31 {
state.midrow_change(element, bufferlist, chunk.style as u32, chunk.underline);
state.midrow_change(self, bufferlist, chunk.style as u32, chunk.underline);
state.style = chunk.style;
state.underline = chunk.underline;
true
@ -442,7 +400,6 @@ impl TtToCea608 {
#[allow(clippy::too_many_arguments)]
fn open_line(
&self,
element: &super::TtToCea608,
state: &mut State,
settings: &Settings,
chunk: &Chunk,
@ -459,7 +416,7 @@ impl TtToCea608 {
if let Some(carriage_return) = carriage_return {
if carriage_return {
*col = settings.origin_column;
state.carriage_return(element, bufferlist);
state.carriage_return(self, bufferlist);
true
} else {
state.send_roll_up_preamble
@ -475,20 +432,14 @@ impl TtToCea608 {
if do_preamble {
match state.mode {
Cea608Mode::RollUp2 => state.roll_up_2(element, bufferlist),
Cea608Mode::RollUp3 => state.roll_up_3(element, bufferlist),
Cea608Mode::RollUp4 => state.roll_up_4(element, bufferlist),
Cea608Mode::RollUp2 => state.roll_up_2(self, bufferlist),
Cea608Mode::RollUp3 => state.roll_up_3(self, bufferlist),
Cea608Mode::RollUp4 => state.roll_up_4(self, bufferlist),
_ => (),
}
if chunk.style != TextStyle::White && indent == 0 {
state.preamble_style(
element,
bufferlist,
row,
chunk.style as u32,
chunk.underline,
);
state.preamble_style(self, bufferlist, row, chunk.style as u32, chunk.underline);
state.style = chunk.style;
} else {
if chunk.style != TextStyle::White {
@ -502,20 +453,14 @@ impl TtToCea608 {
}
state.style = TextStyle::White;
state.preamble_indent(
element,
bufferlist,
row,
(indent * 4) as i32,
chunk.underline,
);
state.preamble_indent(self, bufferlist, row, (indent * 4) as i32, chunk.underline);
}
if state.mode == Cea608Mode::PaintOn {
state.delete_to_end_of_row(element, bufferlist);
state.delete_to_end_of_row(self, bufferlist);
}
state.tab_offset(element, bufferlist, offset);
state.tab_offset(self, bufferlist, offset);
state.underline = chunk.underline;
state.send_roll_up_preamble = false;
@ -524,7 +469,7 @@ impl TtToCea608 {
ret = false;
}
if self.open_chunk(element, state, chunk, bufferlist, *col) {
if self.open_chunk(state, chunk, bufferlist, *col) {
*col += 1;
ret = false
}
@ -540,7 +485,6 @@ impl TtToCea608 {
&self,
mut state: &mut State,
settings: &Settings,
element: &super::TtToCea608,
pts: gst::ClockTime,
duration: gst::ClockTime,
lines: Lines,
@ -564,7 +508,7 @@ impl TtToCea608 {
let frame_no = pts.mul_div_round(fps_n, fps_d).unwrap().seconds();
if state.last_frame_no == 0 {
gst::debug!(CAT, obj: element, "Initial skip to frame no {}", frame_no);
gst::debug!(CAT, imp: self, "Initial skip to frame no {}", frame_no);
state.last_frame_no = pts.mul_div_floor(fps_n, fps_d).unwrap().seconds();
}
@ -573,7 +517,7 @@ impl TtToCea608 {
.unwrap()
.seconds();
state.pad(element, mut_list, frame_no);
state.pad(self, mut_list, frame_no);
let mut cleared = false;
if let Some(mode) = lines.mode {
@ -581,7 +525,7 @@ impl TtToCea608 {
/* Always erase the display when going to or from pop-on */
if state.mode == Cea608Mode::PopOn || mode == Cea608Mode::PopOn {
state.erase_display_frame_no = None;
state.erase_display_memory(element, mut_list);
state.erase_display_memory(self, mut_list);
cleared = true;
}
@ -598,7 +542,7 @@ impl TtToCea608 {
if let Some(clear) = lines.clear {
if clear && !cleared {
state.erase_display_frame_no = None;
state.erase_display_memory(element, mut_list);
state.erase_display_memory(self, mut_list);
if state.mode != Cea608Mode::PopOn && state.mode != Cea608Mode::PaintOn {
state.send_roll_up_preamble = true;
}
@ -607,28 +551,23 @@ impl TtToCea608 {
}
if state.mode == Cea608Mode::PopOn {
state.resume_caption_loading(element, mut_list);
state.cc_data(element, mut_list, erase_non_displayed_memory());
state.resume_caption_loading(self, mut_list);
state.cc_data(self, mut_list, erase_non_displayed_memory());
} else if state.mode == Cea608Mode::PaintOn {
state.resume_direct_captioning(element, mut_list);
state.resume_direct_captioning(self, mut_list);
}
let mut prev_char = 0;
for line in &lines.lines {
gst::log!(CAT, obj: element, "Processing {:?}", line);
gst::log!(CAT, imp: self, "Processing {:?}", line);
if let Some(line_row) = line.row {
row = line_row;
}
if row > 14 {
gst::warning!(
CAT,
obj: element,
"Dropping line after 15th row: {:?}",
line
);
gst::warning!(CAT, imp: self, "Dropping line after 15th row: {:?}", line);
continue;
}
@ -644,13 +583,12 @@ impl TtToCea608 {
for (j, chunk) in line.chunks.iter().enumerate() {
let mut prepend_space = true;
if prev_char != 0 {
state.cc_data(element, mut_list, prev_char);
state.cc_data(self, mut_list, prev_char);
prev_char = 0;
}
if j == 0 {
prepend_space = self.open_line(
element,
state,
settings,
chunk,
@ -659,7 +597,7 @@ impl TtToCea608 {
row as i32,
line.carriage_return,
);
} else if self.open_chunk(element, state, chunk, mut_list, col) {
} else if self.open_chunk(state, chunk, mut_list, col) {
prepend_space = false;
col += 1;
}
@ -690,36 +628,36 @@ impl TtToCea608 {
let mut cc_data = eia608_from_utf8_1(&encoded);
if cc_data == 0 {
gst::warning!(CAT, obj: element, "Not translating UTF8: {}", c);
gst::warning!(CAT, imp: self, "Not translating UTF8: {}", c);
cc_data = *SPACE;
}
if is_basicna(prev_char) {
if is_basicna(cc_data) {
state.bna(element, mut_list, prev_char, cc_data);
state.bna(self, mut_list, prev_char, cc_data);
} else if is_westeu(cc_data) {
// extended characters overwrite the previous character,
// so insert a dummy char then write the extended char
state.bna(element, mut_list, prev_char, *SPACE);
state.cc_data(element, mut_list, cc_data);
state.bna(self, mut_list, prev_char, *SPACE);
state.cc_data(self, mut_list, cc_data);
} else {
state.cc_data(element, mut_list, prev_char);
state.cc_data(element, mut_list, cc_data);
state.cc_data(self, mut_list, prev_char);
state.cc_data(self, mut_list, cc_data);
}
prev_char = 0;
} else if is_westeu(cc_data) {
// extended characters overwrite the previous character,
// so insert a dummy char then write the extended char
state.cc_data(element, mut_list, *SPACE);
state.cc_data(element, mut_list, cc_data);
state.cc_data(self, mut_list, *SPACE);
state.cc_data(self, mut_list, cc_data);
} else if is_basicna(cc_data) {
prev_char = cc_data;
} else {
state.cc_data(element, mut_list, cc_data);
state.cc_data(self, mut_list, cc_data);
}
if is_specialna(cc_data) {
state.resume_caption_loading(element, mut_list);
state.resume_caption_loading(self, mut_list);
}
col += 1;
@ -742,12 +680,11 @@ impl TtToCea608 {
|| col > 31
{
if prev_char != 0 {
state.cc_data(element, mut_list, prev_char);
state.cc_data(self, mut_list, prev_char);
prev_char = 0;
}
self.open_line(
element,
state,
settings,
chunk,
@ -761,7 +698,7 @@ impl TtToCea608 {
if chars.peek().is_some() {
gst::warning!(
CAT,
obj: element,
imp: self,
"Dropping characters after 32nd column: {}",
c
);
@ -773,7 +710,7 @@ impl TtToCea608 {
if state.mode == Cea608Mode::PopOn || state.mode == Cea608Mode::PaintOn {
if prev_char != 0 {
state.cc_data(element, mut_list, prev_char);
state.cc_data(self, mut_list, prev_char);
prev_char = 0;
}
row += 1;
@ -781,13 +718,13 @@ impl TtToCea608 {
}
if prev_char != 0 {
state.cc_data(element, mut_list, prev_char);
state.cc_data(self, mut_list, prev_char);
}
if state.mode == Cea608Mode::PopOn {
/* No need to erase the display at this point, end_of_caption will be equivalent */
state.erase_display_frame_no = None;
state.end_of_caption(element, mut_list);
state.end_of_caption(self, mut_list);
}
state.column = col;
@ -800,7 +737,7 @@ impl TtToCea608 {
Some(state.last_frame_no + timeout.mul_div_round(fps_n, fps_d).unwrap().seconds());
}
state.pad(element, mut_list, state.max_frame_no);
state.pad(self, mut_list, state.max_frame_no);
Ok(bufferlist)
}
@ -808,14 +745,13 @@ impl TtToCea608 {
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::TtToCea608,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: element, "Handling {:?}", buffer);
gst::log!(CAT, imp: self, "Handling {:?}", buffer);
let pts = buffer.pts().ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Stream with timestamped buffers required"]
);
@ -823,8 +759,8 @@ impl TtToCea608 {
})?;
let duration = buffer.duration().ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::StreamError::Format,
["Buffers of stream need to have a duration"]
);
@ -890,7 +826,7 @@ impl TtToCea608 {
}
}
let bufferlist = self.generate(&mut state, &settings, element, pts, duration, lines)?;
let bufferlist = self.generate(&mut state, &settings, pts, duration, lines)?;
drop(settings);
drop(state);
@ -898,7 +834,7 @@ impl TtToCea608 {
self.srcpad.push_list(bufferlist)
}
fn sink_event(&self, pad: &gst::Pad, element: &super::TtToCea608, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
use gst::EventView;
@ -954,7 +890,7 @@ impl TtToCea608 {
gst::debug!(
CAT,
obj: element,
imp: self,
"Initial skip to frame no {}",
state.last_frame_no
);
@ -969,7 +905,7 @@ impl TtToCea608 {
let mut bufferlist = gst::BufferList::new();
let mut_list = bufferlist.get_mut().unwrap();
state.pad(element, mut_list, frame_no);
state.pad(self, mut_list, frame_no);
drop(state);
@ -984,7 +920,7 @@ impl TtToCea608 {
let mut_list = bufferlist.get_mut().unwrap();
state.max_frame_no = erase_display_frame_no;
state.pad(element, mut_list, erase_display_frame_no);
state.pad(self, mut_list, erase_display_frame_no);
drop(state);
@ -993,7 +929,7 @@ impl TtToCea608 {
drop(state);
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::FlushStop(_) => {
let mut state = self.state.lock().unwrap();
@ -1010,9 +946,9 @@ impl TtToCea608 {
drop(settings);
drop(state);
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
}
@ -1030,14 +966,14 @@ impl ObjectSubclass for TtToCea608 {
TtToCea608::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
|this| this.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
TtToCea608::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
|this| this.sink_event(pad, event),
)
})
.flags(gst::PadFlags::FIXED_CAPS)
@ -1093,20 +1029,15 @@ impl ObjectImpl for TtToCea608 {
PROPERTIES.as_ref()
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"mode" => {
let mut state = self.state.lock().unwrap();
@ -1141,7 +1072,7 @@ impl ObjectImpl for TtToCea608 {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"mode" => {
let settings = self.settings.lock().unwrap();
@ -1235,10 +1166,9 @@ impl ElementImpl for TtToCea608 {
#[allow(clippy::single_match)]
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::ReadyToPaused => {
@ -1255,7 +1185,7 @@ impl ElementImpl for TtToCea608 {
_ => (),
}
let ret = self.parent_change_state(element, transition)?;
let ret = self.parent_change_state(transition)?;
match transition {
gst::StateChange::PausedToReady => {

View file

@ -48,15 +48,14 @@ impl TtToJson {
fn sink_chain(
&self,
_pad: &gst::Pad,
element: &super::TtToJson,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let pts = buffer.pts();
let duration = buffer.duration();
let buffer = buffer.into_mapped_buffer_readable().map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to map buffer readable"]
);
@ -65,8 +64,8 @@ impl TtToJson {
})?;
let text = std::str::from_utf8(buffer.as_slice()).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Read,
["Failed to map decode as utf8: {}", err]
);
@ -101,8 +100,8 @@ impl TtToJson {
}
let json = serde_json::to_string(&lines).map_err(|err| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::ResourceError::Write,
["Failed to serialize as json {}", err]
);
@ -120,7 +119,7 @@ impl TtToJson {
self.srcpad.push(buf)
}
fn sink_event(&self, pad: &gst::Pad, element: &super::TtToJson, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -133,8 +132,8 @@ impl TtToJson {
.build();
self.srcpad.push_event(gst::event::Caps::new(&caps))
}
EventView::Eos(_) => pad.event_default(Some(element), event),
_ => pad.event_default(Some(element), event),
EventView::Eos(_) => pad.event_default(Some(&*self.instance()), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
}
@ -197,14 +196,14 @@ impl ObjectSubclass for TtToJson {
TtToJson::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|enc, element| enc.sink_chain(pad, element, buffer),
|enc| enc.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
TtToJson::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.sink_event(pad, element, event),
|enc| enc.sink_event(pad, event),
)
})
.build();
@ -235,20 +234,15 @@ impl ObjectImpl for TtToJson {
PROPERTIES.as_ref()
}
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"mode" => {
let mut settings = self.settings.lock().unwrap();
@ -258,7 +252,7 @@ impl ObjectImpl for TtToJson {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"mode" => {
let settings = self.settings.lock().unwrap();

View file

@ -71,11 +71,7 @@ impl Dav1dDec {
}
}
fn gst_video_format_from_dav1d_picture(
&self,
element: &super::Dav1dDec,
pic: &dav1d::Picture,
) -> gst_video::VideoFormat {
fn gst_video_format_from_dav1d_picture(&self, pic: &dav1d::Picture) -> gst_video::VideoFormat {
let bpc = pic.bits_per_component();
let format_desc = match (pic.pixel_layout(), bpc) {
(dav1d::PixelLayout::I400, Some(dav1d::BitsPerComponent(8))) => "GRAY8",
@ -91,7 +87,7 @@ impl Dav1dDec {
(layout, bpc) => {
gst::warning!(
CAT,
obj: element,
imp: self,
"Unsupported dav1d format {:?}/{:?}",
layout,
bpc
@ -119,20 +115,19 @@ impl Dav1dDec {
}
};
f.parse::<gst_video::VideoFormat>().unwrap_or_else(|_| {
gst::warning!(CAT, obj: element, "Unsupported dav1d format: {}", f);
gst::warning!(CAT, imp: self, "Unsupported dav1d format: {}", f);
gst_video::VideoFormat::Unknown
})
}
fn handle_resolution_change<'s>(
&'s self,
element: &super::Dav1dDec,
mut state_guard: MutexGuard<'s, Option<State>>,
pic: &dav1d::Picture,
) -> Result<MutexGuard<'s, Option<State>>, gst::FlowError> {
let state = state_guard.as_ref().unwrap();
let format = self.gst_video_format_from_dav1d_picture(element, pic);
let format = self.gst_video_format_from_dav1d_picture(pic);
if format == gst_video::VideoFormat::Unknown {
return Err(gst::FlowError::NotNegotiated);
}
@ -152,7 +147,7 @@ impl Dav1dDec {
gst::info!(
CAT,
obj: element,
imp: self,
"Negotiating format {:?} picture dimensions {}x{}",
format,
pic.width(),
@ -162,10 +157,11 @@ impl Dav1dDec {
let input_state = state.input_state.clone();
drop(state_guard);
let instance = self.instance();
let output_state =
element.set_output_state(format, pic.width(), pic.height(), Some(&input_state))?;
element.negotiate(output_state)?;
let out_state = element.output_state().unwrap();
instance.set_output_state(format, pic.width(), pic.height(), Some(&input_state))?;
instance.negotiate(output_state)?;
let out_state = instance.output_state().unwrap();
state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().unwrap();
@ -174,22 +170,21 @@ impl Dav1dDec {
Ok(state_guard)
}
fn flush_decoder(&self, element: &super::Dav1dDec, state: &mut State) {
gst::info!(CAT, obj: element, "Flushing decoder");
fn flush_decoder(&self, state: &mut State) {
gst::info!(CAT, imp: self, "Flushing decoder");
state.decoder.flush();
}
fn send_data(
&self,
element: &super::Dav1dDec,
state_guard: &mut MutexGuard<Option<State>>,
input_buffer: gst::Buffer,
frame: gst_video::VideoCodecFrame,
) -> Result<std::ops::ControlFlow<(), ()>, gst::FlowError> {
gst::trace!(
CAT,
obj: element,
imp: self,
"Sending data to decoder for frame {}",
frame.system_frame_number()
);
@ -210,18 +205,18 @@ impl Dav1dDec {
.send_data(input_data, frame_number, timestamp, duration)
{
Ok(()) => {
gst::trace!(CAT, obj: element, "Decoder returned OK");
gst::trace!(CAT, imp: self, "Decoder returned OK");
Ok(std::ops::ControlFlow::Break(()))
}
Err(err) if err.is_again() => {
gst::trace!(CAT, obj: element, "Decoder returned EAGAIN");
gst::trace!(CAT, imp: self, "Decoder returned EAGAIN");
Ok(std::ops::ControlFlow::Continue(()))
}
Err(err) => {
gst::error!(CAT, "Sending data failed (error code: {})", err);
element.release_frame(frame);
self.instance().release_frame(frame);
gst_video::video_decoder_error!(
element,
&*self.instance(),
1,
gst::StreamError::Decode,
["Sending data failed (error code {})", err]
@ -233,26 +228,25 @@ impl Dav1dDec {
fn send_pending_data(
&self,
element: &super::Dav1dDec,
state_guard: &mut MutexGuard<Option<State>>,
) -> Result<std::ops::ControlFlow<(), ()>, gst::FlowError> {
gst::trace!(CAT, obj: element, "Sending pending data to decoder");
gst::trace!(CAT, imp: self, "Sending pending data to decoder");
let state = state_guard.as_mut().unwrap();
match state.decoder.send_pending_data() {
Ok(()) => {
gst::trace!(CAT, obj: element, "Decoder returned OK");
gst::trace!(CAT, imp: self, "Decoder returned OK");
Ok(std::ops::ControlFlow::Break(()))
}
Err(err) if err.is_again() => {
gst::trace!(CAT, obj: element, "Decoder returned EAGAIN");
gst::trace!(CAT, imp: self, "Decoder returned EAGAIN");
Ok(std::ops::ControlFlow::Continue(()))
}
Err(err) => {
gst::error!(CAT, "Sending data failed (error code: {})", err);
gst_video::video_decoder_error!(
element,
&*self.instance(),
1,
gst::StreamError::Decode,
["Sending data failed (error code {})", err]
@ -264,7 +258,6 @@ impl Dav1dDec {
fn decoded_picture_as_buffer(
&self,
element: &super::Dav1dDec,
state_guard: &mut MutexGuard<Option<State>>,
pic: &dav1d::Picture,
output_state: gst_video::VideoCodecState<gst_video::video_codec_state::Readable>,
@ -304,7 +297,7 @@ impl Dav1dDec {
} else {
gst::trace!(
gst::CAT_PERFORMANCE,
obj: element,
imp: self,
"Copying decoded video frame component {:?}",
component
);
@ -359,71 +352,67 @@ impl Dav1dDec {
fn handle_picture<'s>(
&'s self,
element: &super::Dav1dDec,
mut state_guard: MutexGuard<'s, Option<State>>,
pic: &dav1d::Picture,
) -> Result<MutexGuard<'s, Option<State>>, gst::FlowError> {
gst::trace!(CAT, obj: element, "Handling picture {}", pic.offset());
gst::trace!(CAT, imp: self, "Handling picture {}", pic.offset());
state_guard = self.handle_resolution_change(element, state_guard, pic)?;
state_guard = self.handle_resolution_change(state_guard, pic)?;
let output_state = element
let instance = self.instance();
let output_state = instance
.output_state()
.expect("Output state not set. Shouldn't happen!");
let offset = pic.offset() as i32;
if let Some(mut frame) = element.frame(offset) {
let frame = instance.frame(offset);
if let Some(mut frame) = frame {
let output_buffer =
self.decoded_picture_as_buffer(element, &mut state_guard, pic, output_state)?;
self.decoded_picture_as_buffer(&mut state_guard, pic, output_state)?;
frame.set_output_buffer(output_buffer);
drop(state_guard);
element.finish_frame(frame)?;
instance.finish_frame(frame)?;
Ok(self.state.lock().unwrap())
} else {
gst::warning!(CAT, obj: element, "No frame found for offset {}", offset);
gst::warning!(CAT, imp: self, "No frame found for offset {}", offset);
Ok(state_guard)
}
}
fn drop_decoded_pictures(
&self,
element: &super::Dav1dDec,
state_guard: &mut MutexGuard<Option<State>>,
) {
while let Ok(Some(pic)) = self.pending_pictures(element, state_guard) {
gst::debug!(CAT, obj: element, "Dropping picture {}", pic.offset());
fn drop_decoded_pictures(&self, state_guard: &mut MutexGuard<Option<State>>) {
while let Ok(Some(pic)) = self.pending_pictures(state_guard) {
gst::debug!(CAT, imp: self, "Dropping picture {}", pic.offset());
drop(pic);
}
}
fn pending_pictures(
&self,
element: &super::Dav1dDec,
state_guard: &mut MutexGuard<Option<State>>,
) -> Result<Option<dav1d::Picture>, gst::FlowError> {
gst::trace!(CAT, obj: element, "Retrieving pending picture");
gst::trace!(CAT, imp: self, "Retrieving pending picture");
let state = state_guard.as_mut().unwrap();
match state.decoder.get_picture() {
Ok(pic) => {
gst::trace!(CAT, obj: element, "Retrieved picture {}", pic.offset());
gst::trace!(CAT, imp: self, "Retrieved picture {}", pic.offset());
Ok(Some(pic))
}
Err(err) if err.is_again() => {
gst::trace!(CAT, obj: element, "Decoder needs more data");
gst::trace!(CAT, imp: self, "Decoder needs more data");
Ok(None)
}
Err(err) => {
gst::error!(
CAT,
obj: element,
imp: self,
"Retrieving decoded picture failed (error code {})",
err
);
gst_video::video_decoder_error!(
element,
&*self.instance(),
1,
gst::StreamError::Decode,
["Retrieving decoded picture failed (error code {})", err]
@ -435,11 +424,10 @@ impl Dav1dDec {
fn forward_pending_pictures<'s>(
&'s self,
element: &super::Dav1dDec,
mut state_guard: MutexGuard<'s, Option<State>>,
) -> Result<MutexGuard<Option<State>>, gst::FlowError> {
while let Some(pic) = self.pending_pictures(element, &mut state_guard)? {
state_guard = self.handle_picture(element, state_guard, &pic)?;
while let Some(pic) = self.pending_pictures(&mut state_guard)? {
state_guard = self.handle_picture(state_guard, &pic)?;
}
Ok(state_guard)
@ -516,13 +504,7 @@ impl ObjectImpl for Dav1dDec {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
match pspec.name() {
@ -536,7 +518,7 @@ impl ObjectImpl for Dav1dDec {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
match pspec.name() {
@ -600,7 +582,7 @@ impl ElementImpl for Dav1dDec {
}
impl VideoDecoderImpl for Dav1dDec {
fn src_query(&self, element: &Self::Type, query: &mut gst::QueryRef) -> bool {
fn src_query(&self, query: &mut gst::QueryRef) -> bool {
match query.view_mut() {
gst::QueryViewMut::Latency(q) => {
let state_guard = self.state.lock().unwrap();
@ -613,9 +595,8 @@ impl VideoDecoderImpl for Dav1dDec {
Some(ref state) => match state.output_info {
Some(ref info) => {
let mut upstream_latency = gst::query::Latency::new();
let sinkpad = element.sink_pad();
if sinkpad.peer_query(&mut upstream_latency) {
if self.instance().sink_pad().peer_query(&mut upstream_latency) {
let (live, mut min, mut max) = upstream_latency.result();
// For autodetection: 1 if live, else whatever dav1d gives us
let frame_latency: u64 = if max_frame_delay < 0 && live {
@ -638,7 +619,7 @@ impl VideoDecoderImpl for Dav1dDec {
* gst::ClockTime::SECOND
/ (fps_n as u64);
gst::debug!(CAT, obj: element, "Reporting latency of {}", latency);
gst::debug!(CAT, imp: self, "Reporting latency of {}", latency);
min += latency;
max = max.opt_add(latency);
@ -657,22 +638,21 @@ impl VideoDecoderImpl for Dav1dDec {
None => false,
}
}
_ => VideoDecoderImplExt::parent_src_query(self, element, query),
_ => VideoDecoderImplExt::parent_src_query(self, query),
}
}
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
{
let mut state_guard = self.state.lock().unwrap();
*state_guard = None;
}
self.parent_stop(element)
self.parent_stop()
}
fn set_format(
&self,
element: &Self::Type,
input_state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>,
) -> Result<(), gst::LoggableError> {
let mut state_guard = self.state.lock().unwrap();
@ -681,14 +661,13 @@ impl VideoDecoderImpl for Dav1dDec {
let max_frame_delay: u32;
let n_cpus = num_cpus::get();
gst::info!(CAT, obj: element, "Detected {} logical CPUs", n_cpus);
gst::info!(CAT, imp: self, "Detected {} logical CPUs", n_cpus);
if settings.max_frame_delay == -1 {
let mut latency_query = gst::query::Latency::new();
let mut is_live = false;
let sinkpad = element.sink_pad();
if sinkpad.peer_query(&mut latency_query) {
if self.instance().sink_pad().peer_query(&mut latency_query) {
is_live = latency_query.result().0;
}
@ -699,7 +678,7 @@ impl VideoDecoderImpl for Dav1dDec {
gst::info!(
CAT,
obj: element,
imp: self,
"Creating decoder with n-threads={} and max-frame-delay={}",
settings.n_threads,
max_frame_delay
@ -719,12 +698,11 @@ impl VideoDecoderImpl for Dav1dDec {
n_cpus,
});
self.parent_set_format(element, input_state)
self.parent_set_format(input_state)
}
fn handle_frame(
&self,
element: &Self::Type,
frame: gst_video::VideoCodecFrame,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let input_buffer = frame
@ -733,73 +711,71 @@ impl VideoDecoderImpl for Dav1dDec {
{
let mut state_guard = self.state.lock().unwrap();
state_guard = self.forward_pending_pictures(element, state_guard)?;
if self.send_data(element, &mut state_guard, input_buffer, frame)?
state_guard = self.forward_pending_pictures(state_guard)?;
if self.send_data(&mut state_guard, input_buffer, frame)?
== std::ops::ControlFlow::Continue(())
{
loop {
state_guard = self.forward_pending_pictures(element, state_guard)?;
if self.send_pending_data(element, &mut state_guard)?
== std::ops::ControlFlow::Break(())
state_guard = self.forward_pending_pictures(state_guard)?;
if self.send_pending_data(&mut state_guard)? == std::ops::ControlFlow::Break(())
{
break;
}
}
}
let _state_guard = self.forward_pending_pictures(element, state_guard)?;
let _state_guard = self.forward_pending_pictures(state_guard)?;
}
Ok(gst::FlowSuccess::Ok)
}
fn flush(&self, element: &Self::Type) -> bool {
gst::info!(CAT, obj: element, "Flushing");
fn flush(&self) -> bool {
gst::info!(CAT, imp: self, "Flushing");
{
let mut state_guard = self.state.lock().unwrap();
if state_guard.is_some() {
let state = state_guard.as_mut().unwrap();
self.flush_decoder(element, state);
self.drop_decoded_pictures(element, &mut state_guard);
self.flush_decoder(state);
self.drop_decoded_pictures(&mut state_guard);
}
}
true
}
fn drain(&self, element: &Self::Type) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::info!(CAT, obj: element, "Draining");
fn drain(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::info!(CAT, imp: self, "Draining");
{
let mut state_guard = self.state.lock().unwrap();
if state_guard.is_some() {
let state = state_guard.as_mut().unwrap();
self.flush_decoder(element, state);
let _state_guard = self.forward_pending_pictures(element, state_guard)?;
self.flush_decoder(state);
let _state_guard = self.forward_pending_pictures(state_guard)?;
}
}
self.parent_drain(element)
self.parent_drain()
}
fn finish(&self, element: &Self::Type) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::info!(CAT, obj: element, "Finishing");
fn finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::info!(CAT, imp: self, "Finishing");
{
let mut state_guard = self.state.lock().unwrap();
if state_guard.is_some() {
let state = state_guard.as_mut().unwrap();
self.flush_decoder(element, state);
let _state_guard = self.forward_pending_pictures(element, state_guard)?;
self.flush_decoder(state);
let _state_guard = self.forward_pending_pictures(state_guard)?;
}
}
self.parent_finish(element)
self.parent_finish()
}
fn decide_allocation(
&self,
element: &Self::Type,
query: &mut gst::query::Allocation,
) -> Result<(), gst::LoggableError> {
{
@ -810,6 +786,6 @@ impl VideoDecoderImpl for Dav1dDec {
.is_some();
}
self.parent_decide_allocation(element, query)
self.parent_decide_allocation(query)
}
}

View file

@ -358,7 +358,6 @@ impl VideoDecoderImpl for Ffv1Dec {
/* We allocate the decoder here rather than start() because we need the sink caps */
fn set_format(
&self,
element: &super::Ffv1Dec,
state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>,
) -> Result<(), gst::LoggableError> {
let info = state.info();
@ -372,7 +371,8 @@ impl VideoDecoderImpl for Ffv1Dec {
let format = get_output_format(decoder.config_record())
.ok_or_else(|| gst::loggable_error!(CAT, "Unsupported format"))?;
let output_state = element
let instance = self.instance();
let output_state = instance
.set_output_state(format, info.width(), info.height(), Some(state))
.map_err(|err| gst::loggable_error!(CAT, "Failed to set output params: {}", err))?;
@ -386,23 +386,22 @@ impl VideoDecoderImpl for Ffv1Dec {
};
drop(decoder_state);
element
instance
.negotiate(output_state)
.map_err(|err| gst::loggable_error!(CAT, "Negotiation failed: {}", err))?;
self.parent_set_format(element, state)
self.parent_set_format(state)
}
fn stop(&self, element: &super::Ffv1Dec) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
let mut decoder_state = self.state.lock().unwrap();
*decoder_state = DecoderState::Stopped;
self.parent_stop(element)
self.parent_stop()
}
fn handle_frame(
&self,
element: &super::Ffv1Dec,
mut frame: gst_video::VideoCodecFrame,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state = self.state.lock().unwrap();
@ -438,14 +437,13 @@ impl VideoDecoderImpl for Ffv1Dec {
drop(state);
frame.set_output_buffer(buf);
element.finish_frame(frame)?;
self.instance().finish_frame(frame)?;
Ok(gst::FlowSuccess::Ok)
}
fn decide_allocation(
&self,
element: &Self::Type,
query: &mut gst::query::Allocation,
) -> Result<(), gst::LoggableError> {
let supported = query
@ -461,6 +459,6 @@ impl VideoDecoderImpl for Ffv1Dec {
*video_meta_supported = supported;
}
self.parent_decide_allocation(element, query)
self.parent_decide_allocation(query)
}
}

View file

@ -134,7 +134,7 @@ impl ObjectSubclass for FlvDemux {
FlvDemux::catch_panic_pad_function(
parent,
|| Err(gst::loggable_error!(CAT, "Panic activating sink pad")),
|demux, element| demux.sink_activate(pad, element),
|demux| demux.sink_activate(pad),
)
})
.activatemode_function(|pad, parent, mode, active| {
@ -146,8 +146,8 @@ impl ObjectSubclass for FlvDemux {
"Panic activating sink pad with mode"
))
},
|demux, element| {
demux.sink_activatemode(pad, element, mode, active);
|demux| {
demux.sink_activatemode(pad, mode, active);
Ok(())
},
)
@ -156,14 +156,14 @@ impl ObjectSubclass for FlvDemux {
FlvDemux::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|demux, element| demux.sink_chain(pad, element, buffer),
|demux| demux.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
FlvDemux::catch_panic_pad_function(
parent,
|| false,
|demux, element| demux.sink_event(pad, element, event),
|demux| demux.sink_event(pad, event),
)
})
.build();
@ -180,10 +180,10 @@ impl ObjectSubclass for FlvDemux {
}
impl ObjectImpl for FlvDemux {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
obj.add_pad(&self.sinkpad).unwrap();
self.instance().add_pad(&self.sinkpad).unwrap();
}
}
@ -298,11 +298,7 @@ impl ElementImpl for FlvDemux {
}
impl FlvDemux {
fn sink_activate(
&self,
pad: &gst::Pad,
_element: &super::FlvDemux,
) -> Result<(), gst::LoggableError> {
fn sink_activate(&self, pad: &gst::Pad) -> Result<(), gst::LoggableError> {
let mode = {
let mut query = gst::query::Scheduling::new();
if !pad.peer_query(&mut query) {
@ -327,15 +323,9 @@ impl FlvDemux {
Ok(())
}
fn sink_activatemode(
&self,
_pad: &gst::Pad,
element: &super::FlvDemux,
mode: gst::PadMode,
active: bool,
) {
fn sink_activatemode(&self, _pad: &gst::Pad, mode: gst::PadMode, active: bool) {
if active {
self.start(element, mode);
self.start(mode);
if mode == gst::PadMode::Pull {
// TODO implement pull mode
@ -347,63 +337,58 @@ impl FlvDemux {
let _ = self.sinkpad.stop_task();
}
self.stop(element);
self.stop();
}
}
fn start(&self, _element: &super::FlvDemux, _mode: gst::PadMode) {
fn start(&self, _mode: gst::PadMode) {
*self.state.lock().unwrap() = State::NeedHeader;
}
fn stop(&self, element: &super::FlvDemux) {
fn stop(&self) {
*self.state.lock().unwrap() = State::Stopped;
self.adapter.lock().unwrap().clear();
let mut flow_combiner = self.flow_combiner.lock().unwrap();
if let Some(pad) = self.audio_srcpad.lock().unwrap().take() {
element.remove_pad(&pad).unwrap();
self.instance().remove_pad(&pad).unwrap();
flow_combiner.remove_pad(&pad);
}
if let Some(pad) = self.video_srcpad.lock().unwrap().take() {
element.remove_pad(&pad).unwrap();
self.instance().remove_pad(&pad).unwrap();
flow_combiner.remove_pad(&pad);
}
flow_combiner.reset();
}
fn sink_event(&self, pad: &gst::Pad, element: &super::FlvDemux, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() {
EventView::Eos(..) => {
// TODO implement
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::Segment(..) => {
// TODO implement
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::FlushStart(..) => {
// TODO implement
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::FlushStop(..) => {
// TODO implement
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_query(
&self,
pad: &gst::Pad,
element: &super::FlvDemux,
query: &mut gst::QueryRef,
) -> bool {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut;
match query.view_mut() {
@ -447,11 +432,11 @@ impl FlvDemux {
false
}
}
_ => pad.query_default(Some(element), query),
_ => pad.query_default(Some(&*self.instance()), query),
}
}
fn src_event(&self, pad: &gst::Pad, element: &super::FlvDemux, event: gst::Event) -> bool {
fn src_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
match event.view() {
@ -459,14 +444,13 @@ impl FlvDemux {
// TODO: Implement
false
}
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn sink_chain(
&self,
pad: &gst::Pad,
element: &super::FlvDemux,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@ -479,10 +463,10 @@ impl FlvDemux {
match *state {
State::Stopped => unreachable!(),
State::NeedHeader => {
let header = match self.find_header(element, &mut *adapter) {
let header = match self.find_header(&mut *adapter) {
Ok(header) => header,
Err(_) => {
gst::trace!(CAT, obj: element, "Need more data");
gst::trace!(CAT, imp: self, "Need more data");
return Ok(gst::FlowSuccess::Ok);
}
};
@ -511,7 +495,7 @@ impl FlvDemux {
} => {
let avail = adapter.available();
if avail == 0 {
gst::trace!(CAT, obj: element, "Need more data");
gst::trace!(CAT, imp: self, "Need more data");
return Ok(gst::FlowSuccess::Ok);
}
let skip = cmp::min(avail, *skip_left as usize);
@ -519,24 +503,24 @@ impl FlvDemux {
*skip_left -= skip as u32;
}
State::Streaming(ref mut sstate) => {
let res = sstate.handle_tag(element, &mut *adapter);
let res = sstate.handle_tag(self, &mut *adapter);
match res {
Ok(None) => {
gst::trace!(CAT, obj: element, "Need more data");
gst::trace!(CAT, imp: self, "Need more data");
return Ok(gst::FlowSuccess::Ok);
}
Ok(Some(events)) => {
drop(state);
drop(adapter);
self.handle_events(element, events)?;
self.handle_events(events)?;
adapter = self.adapter.lock().unwrap();
state = self.state.lock().unwrap();
}
Err(err) => {
element.post_error_message(err);
self.post_error_message(err);
return Err(gst::FlowError::Error);
}
}
@ -545,16 +529,12 @@ impl FlvDemux {
}
}
fn find_header(
&self,
element: &super::FlvDemux,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<flavors::Header, ()> {
fn find_header(&self, adapter: &mut gst_base::UniqueAdapter) -> Result<flavors::Header, ()> {
while adapter.available() >= 9 {
let data = adapter.map(9).unwrap();
if let Ok((_, header)) = flavors::header(&*data) {
gst::debug!(CAT, obj: element, "Found FLV header: {:?}", header);
gst::debug!(CAT, imp: self, "Found FLV header: {:?}", header);
drop(data);
adapter.flush(9);
@ -570,7 +550,6 @@ impl FlvDemux {
fn handle_events(
&self,
element: &super::FlvDemux,
events: SmallVec<[Event; 4]>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
for event in events {
@ -582,7 +561,7 @@ impl FlvDemux {
if let Some(ref srcpad) = *audio_srcpad {
srcpad.clone()
} else {
let srcpad = self.create_srcpad(element, "audio", &caps);
let srcpad = self.create_srcpad("audio", &caps);
*audio_srcpad = Some(srcpad.clone());
srcpad
@ -593,7 +572,7 @@ impl FlvDemux {
if let Some(ref srcpad) = *video_srcpad {
srcpad.clone()
} else {
let srcpad = self.create_srcpad(element, "video", &caps);
let srcpad = self.create_srcpad("video", &caps);
*video_srcpad = Some(srcpad.clone());
@ -618,7 +597,7 @@ impl FlvDemux {
let res = pad.push(buffer);
gst::trace!(
CAT,
obj: element,
imp: self,
"Pushing buffer for stream {:?} returned {:?}",
stream,
res
@ -631,7 +610,7 @@ impl FlvDemux {
}
}
Event::HaveAllStreams => {
element.no_more_pads();
self.instance().no_more_pads();
}
}
}
@ -639,28 +618,28 @@ impl FlvDemux {
Ok(gst::FlowSuccess::Ok)
}
fn create_srcpad(&self, element: &super::FlvDemux, name: &str, caps: &gst::Caps) -> gst::Pad {
let templ = element.element_class().pad_template(name).unwrap();
fn create_srcpad(&self, name: &str, caps: &gst::Caps) -> gst::Pad {
let templ = self.instance().element_class().pad_template(name).unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some(name))
.event_function(|pad, parent, event| {
FlvDemux::catch_panic_pad_function(
parent,
|| false,
|demux, element| demux.src_event(pad, element, event),
|demux| demux.src_event(pad, event),
)
})
.query_function(|pad, parent, query| {
FlvDemux::catch_panic_pad_function(
parent,
|| false,
|demux, element| demux.src_query(pad, element, query),
|demux| demux.src_query(pad, query),
)
})
.build();
srcpad.set_active(true).unwrap();
let full_stream_id = srcpad.create_stream_id(element, Some(name));
let full_stream_id = srcpad.create_stream_id(&*self.instance(), Some(name));
// FIXME group id
srcpad.push_event(gst::event::StreamStart::new(&full_stream_id));
srcpad.push_event(gst::event::Caps::new(caps));
@ -671,7 +650,7 @@ impl FlvDemux {
self.flow_combiner.lock().unwrap().add_pad(&srcpad);
element.add_pad(&srcpad).unwrap();
self.instance().add_pad(&srcpad).unwrap();
srcpad
}
@ -694,7 +673,7 @@ impl StreamingState {
fn handle_tag(
&mut self,
element: &super::FlvDemux,
imp: &FlvDemux,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<Option<SmallVec<[Event; 4]>>, gst::ErrorMessage> {
use nom::number::complete::be_u32;
@ -708,7 +687,7 @@ impl StreamingState {
match be_u32::<_, (_, nom::error::ErrorKind)>(&data[0..4]) {
Err(_) => unreachable!(),
Ok((_, previous_size)) => {
gst::trace!(CAT, obj: element, "Previous tag size {}", previous_size);
gst::trace!(CAT, imp: imp, "Previous tag size {}", previous_size);
// Nothing to do here, we just consume it for now
}
}
@ -724,7 +703,7 @@ impl StreamingState {
Ok((_, tag_header)) => tag_header,
};
gst::trace!(CAT, obj: element, "Parsed tag header {:?}", tag_header);
gst::trace!(CAT, imp: imp, "Parsed tag header {:?}", tag_header);
drop(data);
@ -736,19 +715,19 @@ impl StreamingState {
match tag_header.tag_type {
flavors::TagType::Script => {
gst::trace!(CAT, obj: element, "Found script tag");
gst::trace!(CAT, imp: imp, "Found script tag");
Ok(self.handle_script_tag(element, &tag_header, adapter))
Ok(self.handle_script_tag(imp, &tag_header, adapter))
}
flavors::TagType::Audio => {
gst::trace!(CAT, obj: element, "Found audio tag");
gst::trace!(CAT, imp: imp, "Found audio tag");
self.handle_audio_tag(element, &tag_header, adapter)
self.handle_audio_tag(imp, &tag_header, adapter)
}
flavors::TagType::Video => {
gst::trace!(CAT, obj: element, "Found video tag");
gst::trace!(CAT, imp: imp, "Found video tag");
self.handle_video_tag(element, &tag_header, adapter)
self.handle_video_tag(imp, &tag_header, adapter)
}
}
.map(Option::Some)
@ -756,7 +735,7 @@ impl StreamingState {
fn handle_script_tag(
&mut self,
element: &super::FlvDemux,
imp: &FlvDemux,
tag_header: &flavors::TagHeader,
adapter: &mut gst_base::UniqueAdapter,
) -> SmallVec<[Event; 4]> {
@ -768,10 +747,10 @@ impl StreamingState {
match flavors::script_data(&*data) {
Ok((_, ref script_data)) if script_data.name == "onMetaData" => {
gst::trace!(CAT, obj: element, "Got script tag: {:?}", script_data);
gst::trace!(CAT, imp: imp, "Got script tag: {:?}", script_data);
let metadata = Metadata::new(script_data);
gst::debug!(CAT, obj: element, "Got metadata: {:?}", metadata);
gst::debug!(CAT, imp: imp, "Got metadata: {:?}", metadata);
let audio_changed = self
.audio
@ -799,10 +778,10 @@ impl StreamingState {
}
}
Ok((_, ref script_data)) => {
gst::trace!(CAT, obj: element, "Got script tag: {:?}", script_data);
gst::trace!(CAT, imp: imp, "Got script tag: {:?}", script_data);
}
Err(nom::Err::Error(err)) | Err(nom::Err::Failure(err)) => {
gst::error!(CAT, obj: element, "Error parsing script tag: {:?}", err);
gst::error!(CAT, imp: imp, "Error parsing script tag: {:?}", err);
}
Err(nom::Err::Incomplete(_)) => {
// ignore
@ -817,17 +796,12 @@ impl StreamingState {
fn update_audio_stream(
&mut self,
element: &super::FlvDemux,
imp: &FlvDemux,
data_header: &flavors::AudioDataHeader,
) -> SmallVec<[Event; 4]> {
let mut events = SmallVec::new();
gst::trace!(
CAT,
obj: element,
"Got audio data header: {:?}",
data_header
);
gst::trace!(CAT, imp: imp, "Got audio data header: {:?}", data_header);
let new_audio_format =
AudioFormat::new(data_header, &self.metadata, &self.aac_sequence_header);
@ -835,7 +809,7 @@ impl StreamingState {
if self.audio.as_ref() != Some(&new_audio_format) {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Got new audio format: {:?}",
new_audio_format
);
@ -851,7 +825,7 @@ impl StreamingState {
if (!self.expect_video || self.video != None) && self.audio != None && !self.got_all_streams
{
gst::debug!(CAT, obj: element, "Have all expected streams now");
gst::debug!(CAT, imp: imp, "Have all expected streams now");
self.got_all_streams = true;
events.push(Event::HaveAllStreams);
}
@ -861,7 +835,7 @@ impl StreamingState {
fn handle_aac_audio_packet_header(
&mut self,
element: &super::FlvDemux,
imp: &FlvDemux,
tag_header: &flavors::TagHeader,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<bool, gst::ErrorMessage> {
@ -870,7 +844,7 @@ impl StreamingState {
adapter.flush((tag_header.data_size - 1) as usize);
gst::warning!(
CAT,
obj: element,
imp: imp,
"Too small packet for AAC packet header {}",
tag_header.data_size
);
@ -881,19 +855,14 @@ impl StreamingState {
match flavors::aac_audio_packet_header(&*data) {
Err(nom::Err::Error(err)) | Err(nom::Err::Failure(err)) => {
gst::error!(
CAT,
obj: element,
"Invalid AAC audio packet header: {:?}",
err
);
gst::error!(CAT, imp: imp, "Invalid AAC audio packet header: {:?}", err);
drop(data);
adapter.flush((tag_header.data_size - 1) as usize);
Ok(true)
}
Err(nom::Err::Incomplete(_)) => unreachable!(),
Ok((_, header)) => {
gst::trace!(CAT, obj: element, "Got AAC packet header {:?}", header);
gst::trace!(CAT, imp: imp, "Got AAC packet header {:?}", header);
match header.packet_type {
flavors::AACPacketType::SequenceHeader => {
drop(data);
@ -901,7 +870,7 @@ impl StreamingState {
let buffer = adapter
.take_buffer((tag_header.data_size - 1 - 1) as usize)
.unwrap();
gst::debug!(CAT, obj: element, "Got AAC sequence header {:?}", buffer,);
gst::debug!(CAT, imp: imp, "Got AAC sequence header {:?}", buffer,);
self.aac_sequence_header = Some(buffer);
Ok(true)
@ -918,7 +887,7 @@ impl StreamingState {
fn handle_audio_tag(
&mut self,
element: &super::FlvDemux,
imp: &FlvDemux,
tag_header: &flavors::TagHeader,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<SmallVec<[Event; 4]>, gst::ErrorMessage> {
@ -927,7 +896,7 @@ impl StreamingState {
let data = adapter.map(1).unwrap();
let data_header = match flavors::audio_data_header(&*data) {
Err(nom::Err::Error(err)) | Err(nom::Err::Failure(err)) => {
gst::error!(CAT, obj: element, "Invalid audio data header: {:?}", err);
gst::error!(CAT, imp: imp, "Invalid audio data header: {:?}", err);
drop(data);
adapter.flush(tag_header.data_size as usize);
return Ok(SmallVec::new());
@ -938,11 +907,11 @@ impl StreamingState {
drop(data);
adapter.flush(1);
let mut events = self.update_audio_stream(element, &data_header);
let mut events = self.update_audio_stream(imp, &data_header);
// AAC special case
if data_header.sound_format == flavors::SoundFormat::AAC
&& self.handle_aac_audio_packet_header(element, tag_header, adapter)?
&& self.handle_aac_audio_packet_header(imp, tag_header, adapter)?
{
return Ok(events);
}
@ -972,7 +941,7 @@ impl StreamingState {
gst::trace!(
CAT,
obj: element,
imp: imp,
"Outputting audio buffer {:?} for tag {:?}",
buffer,
tag_header,
@ -987,17 +956,12 @@ impl StreamingState {
fn update_video_stream(
&mut self,
element: &super::FlvDemux,
imp: &FlvDemux,
data_header: &flavors::VideoDataHeader,
) -> SmallVec<[Event; 4]> {
let mut events = SmallVec::new();
gst::trace!(
CAT,
obj: element,
"Got video data header: {:?}",
data_header
);
gst::trace!(CAT, imp: imp, "Got video data header: {:?}", data_header);
let new_video_format =
VideoFormat::new(data_header, &self.metadata, &self.avc_sequence_header);
@ -1005,7 +969,7 @@ impl StreamingState {
if self.video.as_ref() != Some(&new_video_format) {
gst::debug!(
CAT,
obj: element,
imp: imp,
"Got new video format: {:?}",
new_video_format
);
@ -1021,7 +985,7 @@ impl StreamingState {
if (!self.expect_audio || self.audio != None) && self.video != None && !self.got_all_streams
{
gst::debug!(CAT, obj: element, "Have all expected streams now");
gst::debug!(CAT, imp: imp, "Have all expected streams now");
self.got_all_streams = true;
events.push(Event::HaveAllStreams);
}
@ -1031,7 +995,7 @@ impl StreamingState {
fn handle_avc_video_packet_header(
&mut self,
element: &super::FlvDemux,
imp: &FlvDemux,
tag_header: &flavors::TagHeader,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<Option<i32>, gst::ErrorMessage> {
@ -1040,7 +1004,7 @@ impl StreamingState {
adapter.flush((tag_header.data_size - 1) as usize);
gst::warning!(
CAT,
obj: element,
imp: imp,
"Too small packet for AVC packet header {}",
tag_header.data_size
);
@ -1050,19 +1014,14 @@ impl StreamingState {
let data = adapter.map(4).unwrap();
match flavors::avc_video_packet_header(&*data) {
Err(nom::Err::Error(err)) | Err(nom::Err::Failure(err)) => {
gst::error!(
CAT,
obj: element,
"Invalid AVC video packet header: {:?}",
err
);
gst::error!(CAT, imp: imp, "Invalid AVC video packet header: {:?}", err);
drop(data);
adapter.flush((tag_header.data_size - 1) as usize);
Ok(None)
}
Err(nom::Err::Incomplete(_)) => unreachable!(),
Ok((_, header)) => {
gst::trace!(CAT, obj: element, "Got AVC packet header {:?}", header);
gst::trace!(CAT, imp: imp, "Got AVC packet header {:?}", header);
match header.packet_type {
flavors::AVCPacketType::SequenceHeader => {
drop(data);
@ -1072,7 +1031,7 @@ impl StreamingState {
.unwrap();
gst::debug!(
CAT,
obj: element,
imp: imp,
"Got AVC sequence header {:?} of size {}",
buffer,
tag_header.data_size - 1 - 4
@ -1099,7 +1058,7 @@ impl StreamingState {
fn handle_video_tag(
&mut self,
element: &super::FlvDemux,
imp: &FlvDemux,
tag_header: &flavors::TagHeader,
adapter: &mut gst_base::UniqueAdapter,
) -> Result<SmallVec<[Event; 4]>, gst::ErrorMessage> {
@ -1108,7 +1067,7 @@ impl StreamingState {
let data = adapter.map(1).unwrap();
let data_header = match flavors::video_data_header(&*data) {
Err(nom::Err::Error(err)) | Err(nom::Err::Failure(err)) => {
gst::error!(CAT, obj: element, "Invalid video data header: {:?}", err);
gst::error!(CAT, imp: imp, "Invalid video data header: {:?}", err);
drop(data);
adapter.flush(tag_header.data_size as usize);
return Ok(SmallVec::new());
@ -1119,11 +1078,11 @@ impl StreamingState {
drop(data);
adapter.flush(1);
let mut events = self.update_video_stream(element, &data_header);
let mut events = self.update_video_stream(imp, &data_header);
// AVC/H264 special case
let cts = if data_header.codec_id == flavors::CodecId::H264 {
match self.handle_avc_video_packet_header(element, tag_header, adapter)? {
match self.handle_avc_video_packet_header(imp, tag_header, adapter)? {
Some(cts) => cts,
None => {
return Ok(events);
@ -1184,7 +1143,7 @@ impl StreamingState {
gst::trace!(
CAT,
obj: element,
imp: imp,
"Outputting video buffer {:?} for tag {:?}, keyframe: {}",
buffer,
tag_header,

View file

@ -168,13 +168,7 @@ impl ObjectImpl for GifEnc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"repeat" => {
let mut settings = self.settings.lock().unwrap();
@ -188,7 +182,7 @@ impl ObjectImpl for GifEnc {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"repeat" => {
let settings = self.settings.lock().unwrap();
@ -251,30 +245,28 @@ impl ElementImpl for GifEnc {
}
impl VideoEncoderImpl for GifEnc {
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = None;
Ok(())
}
fn propose_allocation(
&self,
element: &Self::Type,
query: &mut gst::query::Allocation,
) -> Result<(), gst::LoggableError> {
query.add_allocation_meta::<gst_video::VideoMeta>(None);
self.parent_propose_allocation(element, query)
self.parent_propose_allocation(query)
}
fn set_format(
&self,
element: &Self::Type,
state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>,
) -> Result<(), gst::LoggableError> {
self.flush_encoder(element)
self.flush_encoder()
.map_err(|_| gst::loggable_error!(CAT, "Failed to drain"))?;
let video_info = state.info();
gst::debug!(CAT, obj: element, "Setting format {:?}", video_info);
gst::debug!(CAT, imp: self, "Setting format {:?}", video_info);
{
let mut state = State::new(video_info);
@ -283,23 +275,23 @@ impl VideoEncoderImpl for GifEnc {
*self.state.borrow_mut() = Some(state);
}
let output_state = element
let instance = self.instance();
let output_state = instance
.set_output_state(gst::Caps::builder("image/gif").build(), Some(state))
.map_err(|_| gst::loggable_error!(CAT, "Failed to set output state"))?;
element
instance
.negotiate(output_state)
.map_err(|_| gst::loggable_error!(CAT, "Failed to negotiate"))?;
self.parent_set_format(element, state)
self.parent_set_format(state)
}
fn finish(&self, element: &Self::Type) -> Result<gst::FlowSuccess, gst::FlowError> {
self.flush_encoder(element)
fn finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
self.flush_encoder()
}
fn handle_frame(
&self,
element: &Self::Type,
mut frame: gst_video::VideoCodecFrame,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state_guard = self.state.borrow_mut();
@ -307,7 +299,7 @@ impl VideoEncoderImpl for GifEnc {
gst::debug!(
CAT,
obj: element,
imp: self,
"Sending frame {}",
frame.system_frame_number()
);
@ -318,8 +310,8 @@ impl VideoEncoderImpl for GifEnc {
let in_frame =
gst_video::VideoFrameRef::from_buffer_ref_readable(input_buffer, &state.video_info)
.map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Failed,
["Failed to map output buffer readable"]
);
@ -339,8 +331,8 @@ impl VideoEncoderImpl for GifEnc {
state.gif_pts = pts;
}
let pts = pts.ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Failed,
["No PTS set on input frame. Unable to calculate proper frame timing."]
);
@ -349,8 +341,8 @@ impl VideoEncoderImpl for GifEnc {
let frame_delay = pts
.checked_sub(state.gif_pts.expect("checked above"))
.ok_or_else(|| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Failed,
["Input frame PTS is greater than gif_pts. Unable to calculate proper frame timing."]
);
@ -388,7 +380,7 @@ impl VideoEncoderImpl for GifEnc {
// encode new frame
let context = state.context.as_mut().unwrap();
if let Err(e) = context.write_frame(&gif_frame) {
gst::element_error!(element, gst::CoreError::Failed, [&e.to_string()]);
gst::element_imp_error!(self, gst::CoreError::Failed, [&e.to_string()]);
return Err(gst::FlowError::Error);
}
}
@ -405,13 +397,13 @@ impl VideoEncoderImpl for GifEnc {
// Currently not using incremental frames -> every frame is a keyframe
frame.set_flags(gst_video::VideoCodecFrameFlags::SYNC_POINT);
frame.set_output_buffer(output_buffer);
element.finish_frame(Some(frame))
self.instance().finish_frame(Some(frame))
}
}
impl GifEnc {
fn flush_encoder(&self, element: &super::GifEnc) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::debug!(CAT, obj: element, "Flushing");
fn flush_encoder(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::debug!(CAT, imp: self, "Flushing");
let trailer_buffer = self.state.borrow_mut().as_mut().map(|state| {
// Drop encoder to flush and take flushed data (gif trailer)
@ -433,8 +425,7 @@ impl GifEnc {
});
if let Some(trailer_buffer) = trailer_buffer {
// manually push GIF trailer to the encoder's src pad
let srcpad = element.static_pad("src").unwrap();
srcpad.push(trailer_buffer)?;
self.instance().src_pad().push(trailer_buffer)?;
}
Ok(gst::FlowSuccess::Ok)

View file

@ -80,18 +80,18 @@ impl ObjectImpl for PaintableSink {
PROPERTIES.as_ref()
}
fn property(&self, obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"paintable" => {
let mut paintable = self.paintable.lock().unwrap();
if paintable.is_none() {
obj.initialize_paintable(&mut paintable);
self.instance().initialize_paintable(&mut paintable);
}
let paintable = match &*paintable {
Some(ref paintable) => paintable,
None => {
gst::error!(CAT, obj: obj, "Failed to create paintable");
gst::error!(CAT, imp: self, "Failed to create paintable");
return None::<&gtk::gdk::Paintable>.to_value();
}
};
@ -102,7 +102,7 @@ impl ObjectImpl for PaintableSink {
Err(_) => {
gst::error!(
CAT,
obj: obj,
imp: self,
"Can't retrieve Paintable from non-main thread"
);
None::<&gtk::gdk::Paintable>.to_value()
@ -177,25 +177,24 @@ impl ElementImpl for PaintableSink {
#[allow(clippy::single_match)]
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
match transition {
gst::StateChange::NullToReady => {
let mut paintable = self.paintable.lock().unwrap();
if paintable.is_none() {
element.initialize_paintable(&mut paintable);
self.instance().initialize_paintable(&mut paintable);
}
if paintable.is_none() {
gst::error!(CAT, obj: element, "Failed to create paintable");
gst::error!(CAT, imp: self, "Failed to create paintable");
return Err(gst::StateChangeError);
}
}
_ => (),
}
let res = self.parent_change_state(element, transition);
let res = self.parent_change_state(transition);
match transition {
gst::StateChange::PausedToReady => {
@ -210,8 +209,8 @@ impl ElementImpl for PaintableSink {
}
impl BaseSinkImpl for PaintableSink {
fn set_caps(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
gst::debug!(CAT, obj: element, "Setting caps {:?}", caps);
fn set_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
gst::debug!(CAT, imp: self, "Setting caps {:?}", caps);
let video_info = gst_video::VideoInfo::from_caps(caps)
.map_err(|_| gst::loggable_error!(CAT, "Invalid caps"))?;
@ -223,7 +222,6 @@ impl BaseSinkImpl for PaintableSink {
fn propose_allocation(
&self,
element: &Self::Type,
query: &mut gst::query::Allocation,
) -> Result<(), gst::LoggableError> {
query.add_allocation_meta::<gst_video::VideoMeta>(None);
@ -231,38 +229,34 @@ impl BaseSinkImpl for PaintableSink {
// TODO: Provide a preferred "window size" here for higher-resolution rendering
query.add_allocation_meta::<gst_video::VideoOverlayCompositionMeta>(None);
self.parent_propose_allocation(element, query)
self.parent_propose_allocation(query)
}
}
impl VideoSinkImpl for PaintableSink {
fn show_frame(
&self,
element: &Self::Type,
buffer: &gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::trace!(CAT, obj: element, "Rendering buffer {:?}", buffer);
fn show_frame(&self, buffer: &gst::Buffer) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::trace!(CAT, imp: self, "Rendering buffer {:?}", buffer);
let info = self.info.lock().unwrap();
let info = info.as_ref().ok_or_else(|| {
gst::error!(CAT, obj: element, "Received no caps yet");
gst::error!(CAT, imp: self, "Received no caps yet");
gst::FlowError::NotNegotiated
})?;
let frame = Frame::new(buffer, info).map_err(|err| {
gst::error!(CAT, obj: element, "Failed to map video frame");
gst::error!(CAT, imp: self, "Failed to map video frame");
err
})?;
self.pending_frame.lock().unwrap().replace(frame);
let sender = self.sender.lock().unwrap();
let sender = sender.as_ref().ok_or_else(|| {
gst::error!(CAT, obj: element, "Have no main thread sender");
gst::error!(CAT, imp: self, "Have no main thread sender");
gst::FlowError::Error
})?;
sender.send(SinkEvent::FrameChanged).map_err(|_| {
gst::error!(CAT, obj: element, "Have main thread receiver shut down");
gst::error!(CAT, imp: self, "Have main thread receiver shut down");
gst::FlowError::Error
})?;

View file

@ -45,7 +45,7 @@ impl ObjectSubclass for SinkPaintable {
impl ObjectImpl for SinkPaintable {}
impl PaintableImpl for SinkPaintable {
fn intrinsic_height(&self, _paintable: &Self::Type) -> i32 {
fn intrinsic_height(&self) -> i32 {
if let Some(paintable) = self.paintables.borrow().first() {
f32::round(paintable.height) as i32
} else {
@ -53,7 +53,7 @@ impl PaintableImpl for SinkPaintable {
}
}
fn intrinsic_width(&self, _paintable: &Self::Type) -> i32 {
fn intrinsic_width(&self) -> i32 {
if let Some(paintable) = self.paintables.borrow().first() {
f32::round(paintable.width) as i32
} else {
@ -61,7 +61,7 @@ impl PaintableImpl for SinkPaintable {
}
}
fn intrinsic_aspect_ratio(&self, _paintable: &Self::Type) -> f64 {
fn intrinsic_aspect_ratio(&self) -> f64 {
if let Some(paintable) = self.paintables.borrow().first() {
paintable.width as f64 / paintable.height as f64
} else {
@ -69,13 +69,13 @@ impl PaintableImpl for SinkPaintable {
}
}
fn snapshot(&self, paintable: &Self::Type, snapshot: &gdk::Snapshot, width: f64, height: f64) {
fn snapshot(&self, snapshot: &gdk::Snapshot, width: f64, height: f64) {
let snapshot = snapshot.downcast_ref::<gtk::Snapshot>().unwrap();
let paintables = self.paintables.borrow();
if !paintables.is_empty() {
gst::trace!(CAT, obj: paintable, "Snapshotting frame");
gst::trace!(CAT, imp: self, "Snapshotting frame");
let (frame_width, frame_height) =
paintables.first().map(|p| (p.width, p.height)).unwrap();
@ -125,7 +125,7 @@ impl PaintableImpl for SinkPaintable {
snapshot.pop();
}
} else {
gst::trace!(CAT, obj: paintable, "Snapshotting black frame");
gst::trace!(CAT, imp: self, "Snapshotting black frame");
snapshot.append_color(
&gdk::RGBA::BLACK,
&graphene::Rect::new(0f32, 0f32, width as f32, height as f32),
@ -135,9 +135,9 @@ impl PaintableImpl for SinkPaintable {
}
impl SinkPaintable {
pub(super) fn handle_frame_changed(&self, obj: &super::SinkPaintable, frame: Option<Frame>) {
pub(super) fn handle_frame_changed(&self, frame: Option<Frame>) {
if let Some(frame) = frame {
gst::trace!(CAT, obj: obj, "Received new frame");
gst::trace!(CAT, imp: self, "Received new frame");
let new_paintables = frame.into_textures(&mut *self.cached_textures.borrow_mut());
let new_size = new_paintables
@ -153,15 +153,15 @@ impl SinkPaintable {
if Some(new_size) != old_size {
gst::debug!(
CAT,
obj: obj,
imp: self,
"Size changed from {:?} to {:?}",
old_size,
new_size,
);
obj.invalidate_size();
self.instance().invalidate_size();
}
obj.invalidate_contents();
self.instance().invalidate_contents();
}
}
}

View file

@ -36,6 +36,6 @@ impl Default for SinkPaintable {
impl SinkPaintable {
pub(crate) fn handle_frame_changed(&self, frame: Option<Frame>) {
let imp = self.imp();
imp.handle_frame_changed(self, frame);
imp.handle_frame_changed(frame);
}
}

View file

@ -215,20 +215,14 @@ impl ObjectImpl for HsvDetector {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"hue-ref" => {
let mut settings = self.settings.lock().unwrap();
let hue_ref = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing hue-ref from {} to {}",
settings.hue_ref,
hue_ref
@ -240,7 +234,7 @@ impl ObjectImpl for HsvDetector {
let hue_var = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing hue-var from {} to {}",
settings.hue_var,
hue_var
@ -252,7 +246,7 @@ impl ObjectImpl for HsvDetector {
let saturation_ref = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing saturation-ref from {} to {}",
settings.saturation_ref,
saturation_ref
@ -264,7 +258,7 @@ impl ObjectImpl for HsvDetector {
let saturation_var = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing saturation-var from {} to {}",
settings.saturation_var,
saturation_var
@ -276,7 +270,7 @@ impl ObjectImpl for HsvDetector {
let value_ref = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing value-ref from {} to {}",
settings.value_ref,
value_ref
@ -288,7 +282,7 @@ impl ObjectImpl for HsvDetector {
let value_var = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing value-var from {} to {}",
settings.value_var,
value_var
@ -301,7 +295,7 @@ impl ObjectImpl for HsvDetector {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"hue-ref" => {
let settings = self.settings.lock().unwrap();
@ -390,7 +384,6 @@ impl BaseTransformImpl for HsvDetector {
fn transform_caps(
&self,
element: &Self::Type,
direction: gst::PadDirection,
caps: &gst::Caps,
filter: Option<&gst::Caps>,
@ -408,7 +401,7 @@ impl BaseTransformImpl for HsvDetector {
gst::debug!(
CAT,
obj: element,
imp: self,
"Transformed caps from {} to {} in direction {:?}",
caps,
other_caps,
@ -428,7 +421,6 @@ impl BaseTransformImpl for HsvDetector {
impl VideoFilterImpl for HsvDetector {
fn transform_frame(
&self,
_element: &Self::Type,
in_frame: &gst_video::VideoFrameRef<&gst::BufferRef>,
out_frame: &mut gst_video::VideoFrameRef<&mut gst::BufferRef>,
) -> Result<gst::FlowSuccess, gst::FlowError> {

View file

@ -159,20 +159,14 @@ impl ObjectImpl for HsvFilter {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"hue-shift" => {
let mut settings = self.settings.lock().unwrap();
let hue_shift = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing hue-shift from {} to {}",
settings.hue_shift,
hue_shift
@ -184,7 +178,7 @@ impl ObjectImpl for HsvFilter {
let saturation_mul = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing saturation-mul from {} to {}",
settings.saturation_mul,
saturation_mul
@ -196,7 +190,7 @@ impl ObjectImpl for HsvFilter {
let saturation_off = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing saturation-off from {} to {}",
settings.saturation_off,
saturation_off
@ -208,7 +202,7 @@ impl ObjectImpl for HsvFilter {
let value_mul = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing value-mul from {} to {}",
settings.value_mul,
value_mul
@ -220,7 +214,7 @@ impl ObjectImpl for HsvFilter {
let value_off = value.get().expect("type checked upstream");
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing value-off from {} to {}",
settings.value_off,
value_off
@ -233,7 +227,7 @@ impl ObjectImpl for HsvFilter {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"hue-shift" => {
let settings = self.settings.lock().unwrap();
@ -327,7 +321,6 @@ impl BaseTransformImpl for HsvFilter {
impl VideoFilterImpl for HsvFilter {
fn transform_frame_ip(
&self,
_element: &Self::Type,
frame: &mut gst_video::VideoFrameRef<&mut gst::BufferRef>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
match frame.format() {

View file

@ -348,13 +348,7 @@ impl ObjectImpl for Rav1Enc {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"speed-preset" => {
let mut settings = self.settings.lock().unwrap();
@ -424,7 +418,7 @@ impl ObjectImpl for Rav1Enc {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"speed-preset" => {
let settings = self.settings.lock().unwrap();
@ -555,7 +549,7 @@ impl ElementImpl for Rav1Enc {
}
impl VideoEncoderImpl for Rav1Enc {
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = None;
Ok(())
@ -563,25 +557,23 @@ impl VideoEncoderImpl for Rav1Enc {
fn propose_allocation(
&self,
element: &Self::Type,
query: &mut gst::query::Allocation,
) -> Result<(), gst::LoggableError> {
query.add_allocation_meta::<gst_video::VideoMeta>(None);
self.parent_propose_allocation(element, query)
self.parent_propose_allocation(query)
}
// For the colorimetry mapping below
#[allow(clippy::wildcard_in_or_patterns)]
fn set_format(
&self,
element: &Self::Type,
state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>,
) -> Result<(), gst::LoggableError> {
self.finish(element)
self.finish()
.map_err(|_| gst::loggable_error!(CAT, "Failed to drain"))?;
let video_info = state.info();
gst::debug!(CAT, obj: element, "Setting format {:?}", video_info);
gst::debug!(CAT, imp: self, "Setting format {:?}", video_info);
let settings = self.settings.lock().unwrap();
@ -813,7 +805,8 @@ impl VideoEncoderImpl for Rav1Enc {
video_info,
});
let output_state = element
let instance = self.instance();
let output_state = instance
.set_output_state(
gst::Caps::builder("video/x-av1")
.field("stream-format", "obu-stream")
@ -823,34 +816,34 @@ impl VideoEncoderImpl for Rav1Enc {
Some(state),
)
.map_err(|_| gst::loggable_error!(CAT, "Failed to set output state"))?;
element
instance
.negotiate(output_state)
.map_err(|_| gst::loggable_error!(CAT, "Failed to negotiate"))?;
self.parent_set_format(element, state)
self.parent_set_format(state)
}
fn flush(&self, element: &Self::Type) -> bool {
gst::debug!(CAT, obj: element, "Flushing");
fn flush(&self) -> bool {
gst::debug!(CAT, imp: self, "Flushing");
let mut state_guard = self.state.borrow_mut();
if let Some(ref mut state) = *state_guard {
state.context.flush();
while let Ok(_) | Err(data::EncoderStatus::Encoded) = state.context.receive_packet() {
gst::debug!(CAT, obj: element, "Dropping packet on flush",);
gst::debug!(CAT, imp: self, "Dropping packet on flush",);
}
}
true
}
fn finish(&self, element: &Self::Type) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::debug!(CAT, obj: element, "Finishing");
fn finish(&self) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::debug!(CAT, imp: self, "Finishing");
let mut state_guard = self.state.borrow_mut();
if let Some(ref mut state) = *state_guard {
state.context.flush();
self.output_frames(element, state)?;
self.output_frames(state)?;
}
Ok(gst::FlowSuccess::Ok)
@ -858,17 +851,16 @@ impl VideoEncoderImpl for Rav1Enc {
fn handle_frame(
&self,
element: &Self::Type,
frame: gst_video::VideoCodecFrame,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state_guard = self.state.borrow_mut();
let state = state_guard.as_mut().ok_or(gst::FlowError::NotNegotiated)?;
self.output_frames(element, state)?;
self.output_frames(state)?;
gst::debug!(
CAT,
obj: element,
imp: self,
"Sending frame {}",
frame.system_frame_number()
);
@ -878,8 +870,8 @@ impl VideoEncoderImpl for Rav1Enc {
let in_frame =
gst_video::VideoFrameRef::from_buffer_ref_readable(input_buffer, &state.video_info)
.map_err(|_| {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Failed,
["Failed to map output buffer readable"]
);
@ -894,73 +886,62 @@ impl VideoEncoderImpl for Rav1Enc {
.contains(gst_video::VideoCodecFrameFlags::FORCE_KEYFRAME),
) {
Ok(_) => {
gst::debug!(
CAT,
obj: element,
"Sent frame {}",
frame.system_frame_number()
);
gst::debug!(CAT, imp: self, "Sent frame {}", frame.system_frame_number());
}
Err(data::EncoderStatus::Failure) => {
gst::element_error!(element, gst::CoreError::Failed, ["Failed to send frame"]);
gst::element_imp_error!(self, gst::CoreError::Failed, ["Failed to send frame"]);
return Err(gst::FlowError::Error);
}
Err(_) => (),
}
self.output_frames(element, state)
self.output_frames(state)
}
}
impl Rav1Enc {
fn output_frames(
&self,
element: &super::Rav1Enc,
state: &mut State,
) -> Result<gst::FlowSuccess, gst::FlowError> {
fn output_frames(&self, state: &mut State) -> Result<gst::FlowSuccess, gst::FlowError> {
loop {
match state.context.receive_packet() {
Ok((packet_type, packet_number, frame_number, packet_data)) => {
gst::debug!(
CAT,
obj: element,
imp: self,
"Received packet {} of size {}, frame type {:?}",
packet_number,
packet_data.len(),
packet_type
);
let mut frame = element.frame(frame_number as i32).expect("frame not found");
let instance = self.instance();
let mut frame = instance
.frame(frame_number as i32)
.expect("frame not found");
if packet_type == data::FrameType::KEY {
frame.set_flags(gst_video::VideoCodecFrameFlags::SYNC_POINT);
}
let output_buffer = gst::Buffer::from_mut_slice(packet_data);
frame.set_output_buffer(output_buffer);
element.finish_frame(Some(frame))?;
instance.finish_frame(Some(frame))?;
}
Err(data::EncoderStatus::Encoded) => {
gst::debug!(CAT, obj: element, "Encoded but not output frame yet",);
gst::debug!(CAT, imp: self, "Encoded but not output frame yet",);
}
Err(data::EncoderStatus::NeedMoreData) => {
gst::debug!(CAT, obj: element, "Encoded but need more data",);
gst::debug!(CAT, imp: self, "Encoded but need more data",);
return Ok(gst::FlowSuccess::Ok);
}
Err(data::EncoderStatus::Failure) => {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Failed,
["Failed to receive frame"]
);
return Err(gst::FlowError::Error);
}
Err(err) => {
gst::debug!(
CAT,
obj: element,
"Soft error when receiving frame: {:?}",
err
);
gst::debug!(CAT, imp: self, "Soft error when receiving frame: {:?}", err);
return Ok(gst::FlowSuccess::Ok);
}
}

View file

@ -195,13 +195,7 @@ impl ObjectImpl for PngEncoder {
PROPERTIES.as_ref()
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"compression-level" => {
let mut settings = self.settings.lock();
@ -217,7 +211,7 @@ impl ObjectImpl for PngEncoder {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"compression-level" => {
let settings = self.settings.lock();
@ -283,18 +277,17 @@ impl ElementImpl for PngEncoder {
}
impl VideoEncoderImpl for PngEncoder {
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
*self.state.lock() = None;
Ok(())
}
fn set_format(
&self,
element: &Self::Type,
state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>,
) -> Result<(), gst::LoggableError> {
let video_info = state.info();
gst::debug!(CAT, obj: element, "Setting format {:?}", video_info);
gst::debug!(CAT, imp: self, "Setting format {:?}", video_info);
{
let settings = self.settings.lock();
let mut state = State::new(video_info);
@ -302,17 +295,17 @@ impl VideoEncoderImpl for PngEncoder {
*self.state.lock() = Some(state);
}
let output_state = element
let instance = self.instance();
let output_state = instance
.set_output_state(gst::Caps::builder("image/png").build(), Some(state))
.map_err(|_| gst::loggable_error!(CAT, "Failed to set output state"))?;
element
instance
.negotiate(output_state)
.map_err(|_| gst::loggable_error!(CAT, "Failed to negotiate"))
}
fn handle_frame(
&self,
element: &Self::Type,
mut frame: gst_video::VideoCodecFrame,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state_guard = self.state.lock();
@ -320,7 +313,7 @@ impl VideoEncoderImpl for PngEncoder {
gst::debug!(
CAT,
obj: element,
imp: self,
"Sending frame {}",
frame.system_frame_number()
);
@ -330,7 +323,7 @@ impl VideoEncoderImpl for PngEncoder {
let input_map = input_buffer.map_readable().unwrap();
let data = input_map.as_slice();
state.write_data(data).map_err(|e| {
gst::element_error!(element, gst::CoreError::Failed, [&e.to_string()]);
gst::element_imp_error!(self, gst::CoreError::Failed, [&e.to_string()]);
gst::FlowError::Error
})?;
}
@ -342,6 +335,6 @@ impl VideoEncoderImpl for PngEncoder {
// There are no such incremental frames in the png format
frame.set_flags(gst_video::VideoCodecFrameFlags::SYNC_POINT);
frame.set_output_buffer(output_buffer);
element.finish_frame(Some(frame))
self.instance().finish_frame(Some(frame))
}
}

View file

@ -289,13 +289,7 @@ impl ObjectImpl for RoundedCorners {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"border-radius-px" => {
let mut settings = self.settings.lock().unwrap();
@ -304,20 +298,20 @@ impl ObjectImpl for RoundedCorners {
settings.changed = true;
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing border radius from {} to {}",
settings.border_radius_px,
border_radius
);
settings.border_radius_px = border_radius;
obj.reconfigure_src();
self.instance().reconfigure_src();
}
}
_ => unimplemented!(),
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"border-radius-px" => {
let settings = self.settings.lock().unwrap();
@ -381,17 +375,16 @@ impl BaseTransformImpl for RoundedCorners {
const PASSTHROUGH_ON_SAME_CAPS: bool = false;
const TRANSFORM_IP_ON_PASSTHROUGH: bool = false;
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
let _ = self.state.lock().unwrap().take();
gst::info!(CAT, obj: element, "Stopped");
gst::info!(CAT, imp: self, "Stopped");
Ok(())
}
fn transform_caps(
&self,
element: &Self::Type,
direction: gst::PadDirection,
caps: &gst::Caps,
filter: Option<&gst::Caps>,
@ -438,7 +431,7 @@ impl BaseTransformImpl for RoundedCorners {
gst::debug!(
CAT,
obj: element,
imp: self,
"Transformed caps from {} to {} in direction {:?}",
caps,
other_caps,
@ -452,12 +445,7 @@ impl BaseTransformImpl for RoundedCorners {
}
}
fn set_caps(
&self,
element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
fn set_caps(&self, incaps: &gst::Caps, outcaps: &gst::Caps) -> Result<(), gst::LoggableError> {
let mut settings = self.settings.lock().unwrap();
let out_info = match gst_video::VideoInfo::from_caps(outcaps) {
@ -467,17 +455,17 @@ impl BaseTransformImpl for RoundedCorners {
gst::debug!(
CAT,
obj: element,
imp: self,
"Configured for caps {} to {}",
incaps,
outcaps
);
if out_info.format() == VideoFormat::I420 {
element.set_passthrough(true);
self.instance().set_passthrough(true);
return Ok(());
} else {
element.set_passthrough(false);
self.instance().set_passthrough(false);
}
// See "A420" planar 4:4:2:0 AYUV section
@ -497,10 +485,9 @@ impl BaseTransformImpl for RoundedCorners {
fn prepare_output_buffer(
&self,
element: &Self::Type,
inbuf: InputBuffer,
) -> Result<PrepareOutputBufferSuccess, gst::FlowError> {
if element.is_passthrough() {
if self.instance().is_passthrough() {
return Ok(PrepareOutputBufferSuccess::InputBuffer);
}
@ -509,12 +496,12 @@ impl BaseTransformImpl for RoundedCorners {
settings.changed = false;
gst::debug!(
CAT,
obj: element,
imp: self,
"Caps or border radius changed, generating alpha mask"
);
let state_guard = self.state.lock().unwrap();
let state = state_guard.as_ref().ok_or_else(|| {
gst::element_error!(element, gst::CoreError::Negotiation, ["Have no state yet"]);
gst::element_imp_error!(self, gst::CoreError::Negotiation, ["Have no state yet"]);
gst::FlowError::NotNegotiated
})?;
@ -523,8 +510,8 @@ impl BaseTransformImpl for RoundedCorners {
VideoFormat::A420 => {
drop(state_guard);
if self.generate_alpha_mask(settings.border_radius_px).is_err() {
gst::element_error!(
element,
gst::element_imp_error!(
self,
gst::CoreError::Negotiation,
["Failed to generate alpha mask"]
);
@ -537,7 +524,7 @@ impl BaseTransformImpl for RoundedCorners {
let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().ok_or_else(|| {
gst::element_error!(element, gst::CoreError::Negotiation, ["Have no state yet"]);
gst::element_imp_error!(self, gst::CoreError::Negotiation, ["Have no state yet"]);
gst::FlowError::NotNegotiated
})?;
@ -549,7 +536,7 @@ impl BaseTransformImpl for RoundedCorners {
InputBuffer::Writable(outbuf) => {
gst::log!(
CAT,
obj: element,
imp: self,
"Received writable input buffer of size: {}",
outbuf.size()
);
@ -561,7 +548,7 @@ impl BaseTransformImpl for RoundedCorners {
InputBuffer::Readable(buf) => {
gst::log!(
CAT,
obj: element,
imp: self,
"Received readable input buffer of size: {}",
buf.size()
);
@ -575,21 +562,16 @@ impl BaseTransformImpl for RoundedCorners {
}
}
fn transform_ip(
&self,
_element: &Self::Type,
_buf: &mut gst::BufferRef,
) -> Result<gst::FlowSuccess, gst::FlowError> {
fn transform_ip(&self, _buf: &mut gst::BufferRef) -> Result<gst::FlowSuccess, gst::FlowError> {
Ok(gst::FlowSuccess::Ok)
}
fn propose_allocation(
&self,
element: &Self::Type,
decide_query: Option<&gst::query::Allocation>,
query: &mut gst::query::Allocation,
) -> Result<(), gst::LoggableError> {
query.add_allocation_meta::<gst_video::VideoMeta>(None);
self.parent_propose_allocation(element, decide_query, query)
self.parent_propose_allocation(decide_query, query)
}
}

View file

@ -10,10 +10,10 @@
use gst::glib;
use gst::prelude::*;
pub mod roundedcorners;
mod imp;
glib::wrapper! {
pub struct RoundedCorners(ObjectSubclass<roundedcorners::RoundedCorners>) @extends gst_base::BaseTransform, gst::Element, gst::Object;
pub struct RoundedCorners(ObjectSubclass<imp::RoundedCorners>) @extends gst_base::BaseTransform, gst::Element, gst::Object;
}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {

View file

@ -57,12 +57,11 @@ pub struct ColorDetect {
impl ColorDetect {
fn detect_color(
&self,
element: &super::ColorDetect,
buf: &mut gst::BufferRef,
) -> Result<Option<(String, Vec<Color>)>, gst::FlowError> {
let mut state_guard = self.state.borrow_mut();
let state = state_guard.as_mut().ok_or_else(|| {
gst::element_error!(element, gst::CoreError::Negotiation, ["Have no state yet"]);
gst::element_imp_error!(self, gst::CoreError::Negotiation, ["Have no state yet"]);
gst::FlowError::NotNegotiated
})?;
@ -93,15 +92,10 @@ impl ColorDetect {
Ok(None)
}
fn color_changed(
&self,
element: &super::ColorDetect,
dominant_color_name: &str,
palette: Vec<Color>,
) {
fn color_changed(&self, dominant_color_name: &str, palette: Vec<Color>) {
gst::debug!(
CAT,
obj: element,
imp: self,
"Dominant color changed to {}",
dominant_color_name
);
@ -111,7 +105,7 @@ impl ColorDetect {
.map(|c| ((c.r as u32) << 16) | ((c.g as u32) << 8) | (c.b as u32)),
);
element
self.instance()
.post_message(
gst::message::Element::builder(
gst::structure::Structure::builder("colordetect")
@ -157,13 +151,7 @@ impl ObjectImpl for ColorDetect {
PROPERTIES.as_ref()
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"quality" => {
let mut settings = self.settings.lock().unwrap();
@ -171,7 +159,7 @@ impl ObjectImpl for ColorDetect {
if settings.quality != quality {
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing quality from {} to {}",
settings.quality,
quality
@ -185,7 +173,7 @@ impl ObjectImpl for ColorDetect {
if settings.max_colors != max_colors {
gst::info!(
CAT,
obj: obj,
imp: self,
"Changing max_colors from {} to {}",
settings.max_colors,
max_colors
@ -197,7 +185,7 @@ impl ObjectImpl for ColorDetect {
}
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"quality" => {
let settings = self.settings.lock().unwrap();
@ -268,18 +256,13 @@ impl BaseTransformImpl for ColorDetect {
const PASSTHROUGH_ON_SAME_CAPS: bool = false;
const TRANSFORM_IP_ON_PASSTHROUGH: bool = false;
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
fn stop(&self) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = None;
gst::info!(CAT, obj: element, "Stopped");
gst::info!(CAT, imp: self, "Stopped");
Ok(())
}
fn set_caps(
&self,
element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
fn set_caps(&self, incaps: &gst::Caps, outcaps: &gst::Caps) -> Result<(), gst::LoggableError> {
let in_info = match gst_video::VideoInfo::from_caps(incaps) {
Err(_) => return Err(gst::loggable_error!(CAT, "Failed to parse input caps")),
Ok(info) => info,
@ -292,7 +275,7 @@ impl BaseTransformImpl for ColorDetect {
gst::debug!(
CAT,
obj: element,
imp: self,
"Configured for caps {} to {}",
incaps,
outcaps
@ -320,13 +303,9 @@ impl BaseTransformImpl for ColorDetect {
Ok(())
}
fn transform_ip(
&self,
element: &Self::Type,
buf: &mut gst::BufferRef,
) -> Result<gst::FlowSuccess, gst::FlowError> {
if let Some((dominant_color_name, palette)) = self.detect_color(element, buf)? {
self.color_changed(element, &dominant_color_name, palette);
fn transform_ip(&self, buf: &mut gst::BufferRef) -> Result<gst::FlowSuccess, gst::FlowError> {
if let Some((dominant_color_name, palette)) = self.detect_color(buf)? {
self.color_changed(&dominant_color_name, palette);
}
Ok(gst::FlowSuccess::Ok)

View file

@ -136,7 +136,6 @@ impl WebPDec {
fn sink_chain(
&self,
pad: &gst::Pad,
_element: &super::WebPDec,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst::log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
@ -149,7 +148,7 @@ impl WebPDec {
Ok(gst::FlowSuccess::Ok)
}
fn decode(&self, _element: &super::WebPDec) -> Result<(), gst::ErrorMessage> {
fn decode(&self) -> Result<(), gst::ErrorMessage> {
let mut prev_timestamp: Option<gst::ClockTime> = Some(gst::ClockTime::ZERO);
let mut state = self.state.lock().unwrap();
@ -234,7 +233,7 @@ impl WebPDec {
Ok(())
}
fn sink_event(&self, pad: &gst::Pad, element: &super::WebPDec, event: gst::Event) -> bool {
fn sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
@ -242,26 +241,26 @@ impl WebPDec {
EventView::FlushStop(..) => {
let mut state = self.state.lock().unwrap();
*state = State::default();
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::Eos(..) => {
if let Err(err) = self.decode(element) {
element.post_error_message(err);
if let Err(err) = self.decode() {
self.post_error_message(err);
}
pad.event_default(Some(element), event)
pad.event_default(Some(&*self.instance()), event)
}
EventView::Segment(..) => true,
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
fn src_event(&self, pad: &gst::Pad, element: &super::WebPDec, event: gst::Event) -> bool {
fn src_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView;
gst::log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() {
EventView::Seek(..) => false,
_ => pad.event_default(Some(element), event),
_ => pad.event_default(Some(&*self.instance()), event),
}
}
}
@ -279,14 +278,14 @@ impl ObjectSubclass for WebPDec {
WebPDec::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|dec, element| dec.sink_chain(pad, element, buffer),
|dec| dec.sink_chain(pad, buffer),
)
})
.event_function(|pad, parent, event| {
WebPDec::catch_panic_pad_function(
parent,
|| false,
|dec, element| dec.sink_event(pad, element, event),
|dec| dec.sink_event(pad, event),
)
})
.build();
@ -294,11 +293,7 @@ impl ObjectSubclass for WebPDec {
let templ = klass.pad_template("src").unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
.event_function(|pad, parent, event| {
WebPDec::catch_panic_pad_function(
parent,
|| false,
|dec, element| dec.src_event(pad, element, event),
)
WebPDec::catch_panic_pad_function(parent, || false, |dec| dec.src_event(pad, event))
})
.build();
@ -311,9 +306,10 @@ impl ObjectSubclass for WebPDec {
}
impl ObjectImpl for WebPDec {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
@ -367,15 +363,14 @@ impl ElementImpl for WebPDec {
fn change_state(
&self,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, obj: element, "Changing state {:?}", transition);
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
if transition == gst::StateChange::PausedToReady {
*self.state.lock().unwrap() = State::default();
}
self.parent_change_state(element, transition)
self.parent_change_state(transition)
}
}