mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-12-26 03:50:33 +00:00
jitterbuffer: share context downstream
.. and execute pending futures after pushing buffers
This commit is contained in:
parent
5496067925
commit
202ff408e7
1 changed files with 85 additions and 16 deletions
|
@ -204,6 +204,8 @@ struct State {
|
||||||
discont: bool,
|
discont: bool,
|
||||||
cancel: Option<oneshot::Sender<()>>,
|
cancel: Option<oneshot::Sender<()>>,
|
||||||
last_res: Result<gst::FlowSuccess, gst::FlowError>,
|
last_res: Result<gst::FlowSuccess, gst::FlowError>,
|
||||||
|
pending_future_id: Option<PendingFutureId>,
|
||||||
|
pending_future_cancel: Option<futures::sync::oneshot::Sender<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for State {
|
impl Default for State {
|
||||||
|
@ -232,6 +234,8 @@ impl Default for State {
|
||||||
discont: false,
|
discont: false,
|
||||||
cancel: None,
|
cancel: None,
|
||||||
last_res: Ok(gst::FlowSuccess::Ok),
|
last_res: Ok(gst::FlowSuccess::Ok),
|
||||||
|
pending_future_id: None,
|
||||||
|
pending_future_cancel: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -691,6 +695,29 @@ impl JitterBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send_io_context_event(&self, state: &State) -> Result<gst::FlowSuccess, gst::FlowError> {
|
||||||
|
if self.src_pad.check_reconfigure() {
|
||||||
|
if let (&Some(ref pending_future_id), &Some(ref io_context)) =
|
||||||
|
(&state.pending_future_id, &state.io_context)
|
||||||
|
{
|
||||||
|
let s = gst::Structure::new(
|
||||||
|
"ts-io-context",
|
||||||
|
&[
|
||||||
|
("io-context", &io_context),
|
||||||
|
("pending-future-id", &*pending_future_id),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
let event = gst::Event::new_custom_downstream_sticky(s).build();
|
||||||
|
|
||||||
|
if !self.src_pad.push_event(event) {
|
||||||
|
return Err(gst::FlowError::Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(gst::FlowSuccess::Ok)
|
||||||
|
}
|
||||||
|
|
||||||
fn pop_and_push(
|
fn pop_and_push(
|
||||||
&self,
|
&self,
|
||||||
state: &mut MutexGuard<State>,
|
state: &mut MutexGuard<State>,
|
||||||
|
@ -732,6 +759,8 @@ impl JitterBuffer {
|
||||||
|
|
||||||
gst_debug!(self.cat, obj: &self.src_pad, "Pushing buffer {:?} with seq {}", buffer, seq);
|
gst_debug!(self.cat, obj: &self.src_pad, "Pushing buffer {:?} with seq {}", buffer, seq);
|
||||||
|
|
||||||
|
self.send_io_context_event(&state)?;
|
||||||
|
|
||||||
self.src_pad.push(buffer.to_owned())
|
self.src_pad.push(buffer.to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,8 +810,7 @@ impl JitterBuffer {
|
||||||
.and_then(move |_| {
|
.and_then(move |_| {
|
||||||
let jb = Self::from_instance(&element_clone);
|
let jb = Self::from_instance(&element_clone);
|
||||||
let mut state = jb.state.lock().unwrap();
|
let mut state = jb.state.lock().unwrap();
|
||||||
/* Check earliest_pts after taking the lock again */
|
let now = jb.get_current_running_time(&element_clone);
|
||||||
let mut cont = state.earliest_pts.is_some();
|
|
||||||
|
|
||||||
gst_debug!(
|
gst_debug!(
|
||||||
jb.cat,
|
jb.cat,
|
||||||
|
@ -793,22 +821,41 @@ impl JitterBuffer {
|
||||||
|
|
||||||
let _ = state.cancel.take();
|
let _ = state.cancel.take();
|
||||||
|
|
||||||
while cont {
|
/* Check earliest PTS as we have just taken the lock */
|
||||||
let (head_pts, head_seq) = state.jbuf.borrow().peek();
|
if state.earliest_pts.is_some()
|
||||||
|
&& state.earliest_pts + latency_ns - state.packet_spacing < now
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
let (head_pts, head_seq) = state.jbuf.borrow().peek();
|
||||||
|
|
||||||
if head_pts == state.earliest_pts && head_seq == state.earliest_seqnum as u32 {
|
state.last_res = jb.pop_and_push(&mut state, &element_clone);
|
||||||
cont = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.last_res = jb.pop_and_push(&mut state, &element_clone);
|
if let Some(pending_future_id) = state.pending_future_id {
|
||||||
|
let (cancel, future) = state
|
||||||
|
.io_context
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.drain_pending_futures(pending_future_id);
|
||||||
|
|
||||||
if !cont {
|
state.pending_future_cancel = cancel;
|
||||||
let (earliest_pts, earliest_seqnum) = state.jbuf.borrow().find_earliest();
|
|
||||||
state.earliest_pts = earliest_pts;
|
|
||||||
state.earliest_seqnum = earliest_seqnum as u16;
|
|
||||||
|
|
||||||
if state.earliest_pts.is_some() {
|
state.io_context.as_ref().unwrap().spawn(future);
|
||||||
cont = state.earliest_pts + latency_ns - state.packet_spacing < now;
|
}
|
||||||
|
|
||||||
|
if head_pts == state.earliest_pts
|
||||||
|
&& head_seq == state.earliest_seqnum as u32
|
||||||
|
{
|
||||||
|
let (earliest_pts, earliest_seqnum) =
|
||||||
|
state.jbuf.borrow().find_earliest();
|
||||||
|
state.earliest_pts = earliest_pts;
|
||||||
|
state.earliest_seqnum = earliest_seqnum as u16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.pending_future_cancel.is_some()
|
||||||
|
|| state.earliest_pts.is_none()
|
||||||
|
|| state.earliest_pts + latency_ns - state.packet_spacing >= now
|
||||||
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -885,6 +932,7 @@ impl JitterBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
|
fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
|
||||||
|
let mut forward = true;
|
||||||
use gst::EventView;
|
use gst::EventView;
|
||||||
|
|
||||||
gst_log!(self.cat, obj: pad, "Handling event {:?}", event);
|
gst_log!(self.cat, obj: pad, "Handling event {:?}", event);
|
||||||
|
@ -905,11 +953,21 @@ impl JitterBuffer {
|
||||||
let mut state = self.state.lock().unwrap();
|
let mut state = self.state.lock().unwrap();
|
||||||
self.drain(&mut state, element);
|
self.drain(&mut state, element);
|
||||||
}
|
}
|
||||||
|
EventView::CustomDownstreamSticky(e) => {
|
||||||
|
let s = e.get_structure().unwrap();
|
||||||
|
if s.get_name() == "ts-io-context" {
|
||||||
|
forward = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
|
|
||||||
gst_log!(self.cat, obj: pad, "Forwarding event {:?}", event);
|
if forward {
|
||||||
self.src_pad.push_event(event)
|
gst_log!(self.cat, obj: pad, "Forwarding event {:?}", event);
|
||||||
|
self.src_pad.push_event(event)
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sink_query(
|
fn sink_query(
|
||||||
|
@ -1210,6 +1268,17 @@ impl ElementImpl for JitterBuffer {
|
||||||
|
|
||||||
state.io_context =
|
state.io_context =
|
||||||
Some(IOContext::new(&settings.context, settings.context_wait).unwrap());
|
Some(IOContext::new(&settings.context, settings.context_wait).unwrap());
|
||||||
|
state.pending_future_id = Some(
|
||||||
|
state
|
||||||
|
.io_context
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.acquire_pending_future_id(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
gst::StateChange::PausedToReady => {
|
||||||
|
let mut state = self.state.lock().unwrap();
|
||||||
|
let _ = state.pending_future_cancel.take();
|
||||||
}
|
}
|
||||||
gst::StateChange::ReadyToNull => {
|
gst::StateChange::ReadyToNull => {
|
||||||
let mut state = self.state.lock().unwrap();
|
let mut state = self.state.lock().unwrap();
|
||||||
|
|
Loading…
Reference in a new issue