diff --git a/gst-plugin-threadshare/build.rs b/gst-plugin-threadshare/build.rs index 4ee5fc515..e90dc389b 100644 --- a/gst-plugin-threadshare/build.rs +++ b/gst-plugin-threadshare/build.rs @@ -13,8 +13,8 @@ fn main() { build.include(p); } - build.file("src/rtpjitterbuffer.c"); - build.file("src/rtpstats.c"); + build.file("src/jitterbuffer/rtpjitterbuffer.c"); + build.file("src/jitterbuffer/rtpstats.c"); build.compile("libthreadshare-c.a"); diff --git a/gst-plugin-threadshare/src/jitterbuffer.rs b/gst-plugin-threadshare/src/jitterbuffer/jitterbuffer.rs similarity index 100% rename from gst-plugin-threadshare/src/jitterbuffer.rs rename to gst-plugin-threadshare/src/jitterbuffer/jitterbuffer.rs diff --git a/gst-plugin-threadshare/src/jitterbuffer/mod.rs b/gst-plugin-threadshare/src/jitterbuffer/mod.rs new file mode 100644 index 000000000..bec5e6322 --- /dev/null +++ b/gst-plugin-threadshare/src/jitterbuffer/mod.rs @@ -0,0 +1,424 @@ +// Copyright (C) 2019 Sebastian Dröge +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 51 Franklin Street, Suite 500, +// Boston, MA 02110-1335, USA. + +use glib_sys as glib_ffi; +use gstreamer_sys as gst_ffi; + +pub mod jitterbuffer; + +pub mod ffi { + use glib_ffi::{gboolean, gpointer, GList, GType}; + use glib_sys as glib_ffi; + + use gst_ffi::GstClockTime; + use gstreamer_sys as gst_ffi; + use libc::{c_int, c_uint, c_ulonglong, c_ushort, c_void}; + + #[repr(C)] + #[derive(Copy, Clone)] + pub struct RTPJitterBufferItem { + pub data: gpointer, + pub next: *mut GList, + pub prev: *mut GList, + pub r#type: c_uint, + pub dts: GstClockTime, + pub pts: GstClockTime, + pub seqnum: c_uint, + pub count: c_uint, + pub rtptime: c_uint, + } + + #[repr(C)] + pub struct RTPJitterBuffer(c_void); + + #[repr(C)] + #[derive(Copy, Clone)] + pub struct RTPPacketRateCtx { + probed: gboolean, + clock_rate: c_int, + last_seqnum: c_ushort, + last_ts: c_ulonglong, + avg_packet_rate: c_uint, + } + + pub type RTPJitterBufferMode = c_int; + pub const RTP_JITTER_BUFFER_MODE_NONE: RTPJitterBufferMode = 0; + pub const RTP_JITTER_BUFFER_MODE_SLAVE: RTPJitterBufferMode = 1; + pub const RTP_JITTER_BUFFER_MODE_BUFFER: RTPJitterBufferMode = 2; + pub const RTP_JITTER_BUFFER_MODE_SYNCED: RTPJitterBufferMode = 4; + + extern "C" { + pub fn rtp_jitter_buffer_new() -> *mut RTPJitterBuffer; + pub fn rtp_jitter_buffer_get_type() -> GType; + pub fn rtp_jitter_buffer_get_mode(jbuf: *mut RTPJitterBuffer) -> RTPJitterBufferMode; + pub fn rtp_jitter_buffer_set_mode(jbuf: *mut RTPJitterBuffer, mode: RTPJitterBufferMode); + pub fn rtp_jitter_buffer_get_delay(jbuf: *mut RTPJitterBuffer) -> GstClockTime; + pub fn rtp_jitter_buffer_set_delay(jbuf: *mut RTPJitterBuffer, delay: GstClockTime); + pub fn rtp_jitter_buffer_set_clock_rate(jbuf: *mut RTPJitterBuffer, clock_rate: c_uint); + pub fn rtp_jitter_buffer_get_clock_rate(jbuf: *mut RTPJitterBuffer) -> c_uint; + pub fn rtp_jitter_buffer_reset_skew(jbuf: *mut RTPJitterBuffer); + + pub fn rtp_jitter_buffer_flush(jbuf: *mut RTPJitterBuffer, free_func: glib_ffi::GFunc); + pub fn rtp_jitter_buffer_find_earliest( + jbuf: *mut RTPJitterBuffer, + pts: *mut GstClockTime, + seqnum: *mut c_uint, + ); + pub fn rtp_jitter_buffer_calculate_pts( + jbuf: *mut RTPJitterBuffer, + dts: GstClockTime, + estimated_dts: gboolean, + rtptime: c_uint, + base_time: GstClockTime, + gap: c_int, + is_rtx: gboolean, + ) -> GstClockTime; + pub fn rtp_jitter_buffer_insert( + jbuf: *mut RTPJitterBuffer, + item: *mut RTPJitterBufferItem, + head: *mut gboolean, + percent: *mut c_int, + ) -> gboolean; + pub fn rtp_jitter_buffer_pop( + jbuf: *mut RTPJitterBuffer, + percent: *mut c_int, + ) -> *mut RTPJitterBufferItem; + pub fn rtp_jitter_buffer_peek(jbuf: *mut RTPJitterBuffer) -> *mut RTPJitterBufferItem; + + pub fn gst_rtp_packet_rate_ctx_reset(ctx: *mut RTPPacketRateCtx, clock_rate: c_int); + pub fn gst_rtp_packet_rate_ctx_update( + ctx: *mut RTPPacketRateCtx, + seqnum: c_ushort, + ts: c_uint, + ) -> c_uint; + pub fn gst_rtp_packet_rate_ctx_get_max_dropout( + ctx: *mut RTPPacketRateCtx, + time_ms: c_int, + ) -> c_uint; + pub fn gst_rtp_packet_rate_ctx_get_max_disorder( + ctx: *mut RTPPacketRateCtx, + time_ms: c_int, + ) -> c_uint; + } +} + +use glib::prelude::*; +use glib::translate::*; +use glib::{glib_object_wrapper, glib_wrapper}; + +use std::mem; +use std::ptr; + +glib_wrapper! { + pub struct RTPJitterBuffer(Object); + + match fn { + get_type => || ffi::rtp_jitter_buffer_get_type(), + } +} + +unsafe impl glib::SendUnique for RTPJitterBuffer { + fn is_unique(&self) -> bool { + self.ref_count() == 1 + } +} + +impl ToGlib for RTPJitterBufferMode { + type GlibType = ffi::RTPJitterBufferMode; + + fn to_glib(&self) -> ffi::RTPJitterBufferMode { + match *self { + RTPJitterBufferMode::None => ffi::RTP_JITTER_BUFFER_MODE_NONE, + RTPJitterBufferMode::Slave => ffi::RTP_JITTER_BUFFER_MODE_SLAVE, + RTPJitterBufferMode::Buffer => ffi::RTP_JITTER_BUFFER_MODE_BUFFER, + RTPJitterBufferMode::Synced => ffi::RTP_JITTER_BUFFER_MODE_SYNCED, + RTPJitterBufferMode::__Unknown(value) => value, + } + } +} + +impl FromGlib for RTPJitterBufferMode { + fn from_glib(value: ffi::RTPJitterBufferMode) -> Self { + match value { + 0 => RTPJitterBufferMode::None, + 1 => RTPJitterBufferMode::Slave, + 2 => RTPJitterBufferMode::Buffer, + 4 => RTPJitterBufferMode::Synced, + value => RTPJitterBufferMode::__Unknown(value), + } + } +} + +pub struct RTPJitterBufferItem(Option>); + +unsafe impl Send for RTPJitterBufferItem {} + +impl RTPJitterBufferItem { + pub fn new( + buffer: gst::Buffer, + dts: gst::ClockTime, + pts: gst::ClockTime, + seqnum: u32, + rtptime: u32, + ) -> RTPJitterBufferItem { + unsafe { + RTPJitterBufferItem(Some(Box::new(ffi::RTPJitterBufferItem { + data: buffer.into_ptr() as *mut _, + next: ptr::null_mut(), + prev: ptr::null_mut(), + r#type: 0, + dts: dts.to_glib(), + pts: pts.to_glib(), + seqnum, + count: 1, + rtptime, + }))) + } + } + + pub fn get_buffer(&self) -> gst::Buffer { + unsafe { + let item = self.0.as_ref().expect("Invalid wrapper"); + let buf = item.data as *mut gst_ffi::GstBuffer; + from_glib_none(buf) + } + } + + pub fn get_dts(&self) -> gst::ClockTime { + let item = self.0.as_ref().expect("Invalid wrapper"); + if item.dts == gst_ffi::GST_CLOCK_TIME_NONE { + gst::CLOCK_TIME_NONE + } else { + gst::ClockTime(Some(item.dts)) + } + } + + pub fn get_pts(&self) -> gst::ClockTime { + let item = self.0.as_ref().expect("Invalid wrapper"); + if item.pts == gst_ffi::GST_CLOCK_TIME_NONE { + gst::CLOCK_TIME_NONE + } else { + gst::ClockTime(Some(item.pts)) + } + } + + pub fn get_seqnum(&self) -> u32 { + let item = self.0.as_ref().expect("Invalid wrapper"); + item.seqnum + } + + pub fn get_rtptime(&self) -> u32 { + let item = self.0.as_ref().expect("Invalid wrapper"); + item.rtptime + } +} + +impl Drop for RTPJitterBufferItem { + fn drop(&mut self) { + unsafe { + if let Some(ref item) = self.0 { + gst_ffi::gst_mini_object_unref(item.data as *mut _) + } + } + } +} + +pub struct RTPPacketRateCtx(Box); + +unsafe impl Send for RTPPacketRateCtx {} + +impl RTPPacketRateCtx { + pub fn new() -> RTPPacketRateCtx { + unsafe { + let mut ptr = std::mem::MaybeUninit::uninit(); + ffi::gst_rtp_packet_rate_ctx_reset(ptr.as_mut_ptr(), -1); + RTPPacketRateCtx(Box::new(ptr.assume_init())) + } + } + + pub fn reset(&mut self, clock_rate: i32) { + unsafe { ffi::gst_rtp_packet_rate_ctx_reset(&mut *self.0, clock_rate) } + } + + pub fn update(&mut self, seqnum: u16, ts: u32) -> u32 { + unsafe { ffi::gst_rtp_packet_rate_ctx_update(&mut *self.0, seqnum, ts) } + } + + pub fn get_max_dropout(&mut self, time_ms: i32) -> u32 { + unsafe { ffi::gst_rtp_packet_rate_ctx_get_max_dropout(&mut *self.0, time_ms) } + } + + pub fn get_max_disorder(&mut self, time_ms: i32) -> u32 { + unsafe { ffi::gst_rtp_packet_rate_ctx_get_max_disorder(&mut *self.0, time_ms) } + } +} + +impl Default for RTPPacketRateCtx { + fn default() -> Self { + RTPPacketRateCtx::new() + } +} + +#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)] +pub enum RTPJitterBufferMode { + r#None, + Slave, + Buffer, + Synced, + __Unknown(i32), +} + +impl RTPJitterBuffer { + pub fn new() -> RTPJitterBuffer { + unsafe { from_glib_full(ffi::rtp_jitter_buffer_new()) } + } + + pub fn get_mode(&self) -> RTPJitterBufferMode { + unsafe { from_glib(ffi::rtp_jitter_buffer_get_mode(self.to_glib_none().0)) } + } + + pub fn set_mode(&self, mode: RTPJitterBufferMode) { + unsafe { ffi::rtp_jitter_buffer_set_mode(self.to_glib_none().0, mode.to_glib()) } + } + + pub fn get_delay(&self) -> gst::ClockTime { + unsafe { from_glib(ffi::rtp_jitter_buffer_get_delay(self.to_glib_none().0)) } + } + + pub fn set_delay(&self, delay: gst::ClockTime) { + unsafe { ffi::rtp_jitter_buffer_set_delay(self.to_glib_none().0, delay.to_glib()) } + } + + pub fn set_clock_rate(&self, clock_rate: u32) { + unsafe { ffi::rtp_jitter_buffer_set_clock_rate(self.to_glib_none().0, clock_rate) } + } + + pub fn get_clock_rate(&self) -> u32 { + unsafe { ffi::rtp_jitter_buffer_get_clock_rate(self.to_glib_none().0) } + } + + pub fn calculate_pts( + &self, + dts: gst::ClockTime, + estimated_dts: bool, + rtptime: u32, + base_time: gst::ClockTime, + gap: i32, + is_rtx: bool, + ) -> gst::ClockTime { + unsafe { + let pts = ffi::rtp_jitter_buffer_calculate_pts( + self.to_glib_none().0, + dts.to_glib(), + estimated_dts.to_glib(), + rtptime, + base_time.to_glib(), + gap, + is_rtx.to_glib(), + ); + + if pts == gst_ffi::GST_CLOCK_TIME_NONE { + gst::CLOCK_TIME_NONE + } else { + pts.into() + } + } + } + + pub fn insert(&self, mut item: RTPJitterBufferItem) -> (bool, bool, i32) { + unsafe { + let mut head = mem::MaybeUninit::uninit(); + let mut percent = mem::MaybeUninit::uninit(); + let box_ = item.0.take().expect("Invalid wrapper"); + let ptr = Box::into_raw(box_); + let ret: bool = from_glib(ffi::rtp_jitter_buffer_insert( + self.to_glib_none().0, + ptr, + head.as_mut_ptr(), + percent.as_mut_ptr(), + )); + if !ret { + item.0 = Some(Box::from_raw(ptr)); + } + (ret, from_glib(head.assume_init()), percent.assume_init()) + } + } + + pub fn find_earliest(&self) -> (gst::ClockTime, u32) { + unsafe { + let mut pts = mem::MaybeUninit::uninit(); + let mut seqnum = mem::MaybeUninit::uninit(); + + ffi::rtp_jitter_buffer_find_earliest( + self.to_glib_none().0, + pts.as_mut_ptr(), + seqnum.as_mut_ptr(), + ); + let pts = pts.assume_init(); + let seqnum = seqnum.assume_init(); + + if pts == gst_ffi::GST_CLOCK_TIME_NONE { + (gst::CLOCK_TIME_NONE, seqnum) + } else { + (pts.into(), seqnum) + } + } + } + + pub fn pop(&self) -> (RTPJitterBufferItem, i32) { + unsafe { + let mut percent = mem::MaybeUninit::uninit(); + let item = ffi::rtp_jitter_buffer_pop(self.to_glib_none().0, percent.as_mut_ptr()); + + ( + RTPJitterBufferItem(Some(Box::from_raw(item))), + percent.assume_init(), + ) + } + } + + pub fn peek(&self) -> (gst::ClockTime, u32) { + unsafe { + let item = ffi::rtp_jitter_buffer_peek(self.to_glib_none().0); + if item.is_null() { + (gst::CLOCK_TIME_NONE, std::u32::MAX) + } else { + ((*item).pts.into(), (*item).seqnum) + } + } + } + + pub fn flush(&self) { + unsafe extern "C" fn free_item(item: glib_ffi::gpointer, _: glib_ffi::gpointer) { + let _ = RTPJitterBufferItem(Some(Box::from_raw(item as *mut _))); + } + + unsafe { + ffi::rtp_jitter_buffer_flush(self.to_glib_none().0, Some(free_item)); + } + } + + pub fn reset_skew(&self) { + unsafe { ffi::rtp_jitter_buffer_reset_skew(self.to_glib_none().0) } + } +} + +impl Default for RTPJitterBuffer { + fn default() -> Self { + RTPJitterBuffer::new() + } +} diff --git a/gst-plugin-threadshare/src/rtpjitterbuffer.c b/gst-plugin-threadshare/src/jitterbuffer/rtpjitterbuffer.c similarity index 100% rename from gst-plugin-threadshare/src/rtpjitterbuffer.c rename to gst-plugin-threadshare/src/jitterbuffer/rtpjitterbuffer.c diff --git a/gst-plugin-threadshare/src/rtpjitterbuffer.h b/gst-plugin-threadshare/src/jitterbuffer/rtpjitterbuffer.h similarity index 100% rename from gst-plugin-threadshare/src/rtpjitterbuffer.h rename to gst-plugin-threadshare/src/jitterbuffer/rtpjitterbuffer.h diff --git a/gst-plugin-threadshare/src/rtpstats.c b/gst-plugin-threadshare/src/jitterbuffer/rtpstats.c similarity index 100% rename from gst-plugin-threadshare/src/rtpstats.c rename to gst-plugin-threadshare/src/jitterbuffer/rtpstats.c diff --git a/gst-plugin-threadshare/src/rtpstats.h b/gst-plugin-threadshare/src/jitterbuffer/rtpstats.h similarity index 100% rename from gst-plugin-threadshare/src/rtpstats.h rename to gst-plugin-threadshare/src/jitterbuffer/rtpstats.h diff --git a/gst-plugin-threadshare/src/lib.rs b/gst-plugin-threadshare/src/lib.rs index 0748fcde9..4add7f9db 100644 --- a/gst-plugin-threadshare/src/lib.rs +++ b/gst-plugin-threadshare/src/lib.rs @@ -39,6 +39,7 @@ mod jitterbuffer; mod proxy; mod queue; +use glib::translate::*; use glib_sys as glib_ffi; use gst; @@ -51,7 +52,7 @@ fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { queue::register(plugin)?; proxy::register(plugin)?; appsrc::register(plugin)?; - jitterbuffer::register(plugin)?; + jitterbuffer::jitterbuffer::register(plugin)?; Ok(()) } @@ -97,406 +98,3 @@ impl<'a> Drop for MutexGuard<'a> { } } } - -pub mod ffi { - use glib_ffi::{gboolean, gpointer, GList, GType}; - use glib_sys as glib_ffi; - - use gst_ffi::GstClockTime; - use gstreamer_sys as gst_ffi; - use libc::{c_int, c_uint, c_ulonglong, c_ushort, c_void}; - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct RTPJitterBufferItem { - pub data: gpointer, - pub next: *mut GList, - pub prev: *mut GList, - pub r#type: c_uint, - pub dts: GstClockTime, - pub pts: GstClockTime, - pub seqnum: c_uint, - pub count: c_uint, - pub rtptime: c_uint, - } - - #[repr(C)] - pub struct RTPJitterBuffer(c_void); - - #[repr(C)] - #[derive(Copy, Clone)] - pub struct RTPPacketRateCtx { - probed: gboolean, - clock_rate: c_int, - last_seqnum: c_ushort, - last_ts: c_ulonglong, - avg_packet_rate: c_uint, - } - - pub type RTPJitterBufferMode = c_int; - pub const RTP_JITTER_BUFFER_MODE_NONE: RTPJitterBufferMode = 0; - pub const RTP_JITTER_BUFFER_MODE_SLAVE: RTPJitterBufferMode = 1; - pub const RTP_JITTER_BUFFER_MODE_BUFFER: RTPJitterBufferMode = 2; - pub const RTP_JITTER_BUFFER_MODE_SYNCED: RTPJitterBufferMode = 4; - - extern "C" { - pub fn rtp_jitter_buffer_new() -> *mut RTPJitterBuffer; - pub fn rtp_jitter_buffer_get_type() -> GType; - pub fn rtp_jitter_buffer_get_mode(jbuf: *mut RTPJitterBuffer) -> RTPJitterBufferMode; - pub fn rtp_jitter_buffer_set_mode(jbuf: *mut RTPJitterBuffer, mode: RTPJitterBufferMode); - pub fn rtp_jitter_buffer_get_delay(jbuf: *mut RTPJitterBuffer) -> GstClockTime; - pub fn rtp_jitter_buffer_set_delay(jbuf: *mut RTPJitterBuffer, delay: GstClockTime); - pub fn rtp_jitter_buffer_set_clock_rate(jbuf: *mut RTPJitterBuffer, clock_rate: c_uint); - pub fn rtp_jitter_buffer_get_clock_rate(jbuf: *mut RTPJitterBuffer) -> c_uint; - pub fn rtp_jitter_buffer_reset_skew(jbuf: *mut RTPJitterBuffer); - - pub fn rtp_jitter_buffer_flush(jbuf: *mut RTPJitterBuffer, free_func: glib_ffi::GFunc); - pub fn rtp_jitter_buffer_find_earliest( - jbuf: *mut RTPJitterBuffer, - pts: *mut GstClockTime, - seqnum: *mut c_uint, - ); - pub fn rtp_jitter_buffer_calculate_pts( - jbuf: *mut RTPJitterBuffer, - dts: GstClockTime, - estimated_dts: gboolean, - rtptime: c_uint, - base_time: GstClockTime, - gap: c_int, - is_rtx: gboolean, - ) -> GstClockTime; - pub fn rtp_jitter_buffer_insert( - jbuf: *mut RTPJitterBuffer, - item: *mut RTPJitterBufferItem, - head: *mut gboolean, - percent: *mut c_int, - ) -> gboolean; - pub fn rtp_jitter_buffer_pop( - jbuf: *mut RTPJitterBuffer, - percent: *mut c_int, - ) -> *mut RTPJitterBufferItem; - pub fn rtp_jitter_buffer_peek(jbuf: *mut RTPJitterBuffer) -> *mut RTPJitterBufferItem; - - pub fn gst_rtp_packet_rate_ctx_reset(ctx: *mut RTPPacketRateCtx, clock_rate: c_int); - pub fn gst_rtp_packet_rate_ctx_update( - ctx: *mut RTPPacketRateCtx, - seqnum: c_ushort, - ts: c_uint, - ) -> c_uint; - pub fn gst_rtp_packet_rate_ctx_get_max_dropout( - ctx: *mut RTPPacketRateCtx, - time_ms: c_int, - ) -> c_uint; - pub fn gst_rtp_packet_rate_ctx_get_max_disorder( - ctx: *mut RTPPacketRateCtx, - time_ms: c_int, - ) -> c_uint; - } -} - -use glib::prelude::*; -use glib::translate::*; -use glib::{glib_object_wrapper, glib_wrapper}; - -use std::mem; -use std::ptr; - -glib_wrapper! { - pub struct RTPJitterBuffer(Object); - - match fn { - get_type => || ffi::rtp_jitter_buffer_get_type(), - } -} - -unsafe impl glib::SendUnique for RTPJitterBuffer { - fn is_unique(&self) -> bool { - self.ref_count() == 1 - } -} - -impl ToGlib for RTPJitterBufferMode { - type GlibType = ffi::RTPJitterBufferMode; - - fn to_glib(&self) -> ffi::RTPJitterBufferMode { - match *self { - RTPJitterBufferMode::None => ffi::RTP_JITTER_BUFFER_MODE_NONE, - RTPJitterBufferMode::Slave => ffi::RTP_JITTER_BUFFER_MODE_SLAVE, - RTPJitterBufferMode::Buffer => ffi::RTP_JITTER_BUFFER_MODE_BUFFER, - RTPJitterBufferMode::Synced => ffi::RTP_JITTER_BUFFER_MODE_SYNCED, - RTPJitterBufferMode::__Unknown(value) => value, - } - } -} - -impl FromGlib for RTPJitterBufferMode { - fn from_glib(value: ffi::RTPJitterBufferMode) -> Self { - match value { - 0 => RTPJitterBufferMode::None, - 1 => RTPJitterBufferMode::Slave, - 2 => RTPJitterBufferMode::Buffer, - 4 => RTPJitterBufferMode::Synced, - value => RTPJitterBufferMode::__Unknown(value), - } - } -} - -pub struct RTPJitterBufferItem(Option>); - -unsafe impl Send for RTPJitterBufferItem {} - -impl RTPJitterBufferItem { - pub fn new( - buffer: gst::Buffer, - dts: gst::ClockTime, - pts: gst::ClockTime, - seqnum: u32, - rtptime: u32, - ) -> RTPJitterBufferItem { - unsafe { - RTPJitterBufferItem(Some(Box::new(ffi::RTPJitterBufferItem { - data: buffer.into_ptr() as *mut _, - next: ptr::null_mut(), - prev: ptr::null_mut(), - r#type: 0, - dts: dts.to_glib(), - pts: pts.to_glib(), - seqnum, - count: 1, - rtptime, - }))) - } - } - - pub fn get_buffer(&self) -> gst::Buffer { - unsafe { - let item = self.0.as_ref().expect("Invalid wrapper"); - let buf = item.data as *mut gst_ffi::GstBuffer; - from_glib_none(buf) - } - } - - pub fn get_dts(&self) -> gst::ClockTime { - let item = self.0.as_ref().expect("Invalid wrapper"); - if item.dts == gst_ffi::GST_CLOCK_TIME_NONE { - gst::CLOCK_TIME_NONE - } else { - gst::ClockTime(Some(item.dts)) - } - } - - pub fn get_pts(&self) -> gst::ClockTime { - let item = self.0.as_ref().expect("Invalid wrapper"); - if item.pts == gst_ffi::GST_CLOCK_TIME_NONE { - gst::CLOCK_TIME_NONE - } else { - gst::ClockTime(Some(item.pts)) - } - } - - pub fn get_seqnum(&self) -> u32 { - let item = self.0.as_ref().expect("Invalid wrapper"); - item.seqnum - } - - pub fn get_rtptime(&self) -> u32 { - let item = self.0.as_ref().expect("Invalid wrapper"); - item.rtptime - } -} - -impl Drop for RTPJitterBufferItem { - fn drop(&mut self) { - unsafe { - if let Some(ref item) = self.0 { - gst_ffi::gst_mini_object_unref(item.data as *mut _) - } - } - } -} - -pub struct RTPPacketRateCtx(Box); - -unsafe impl Send for RTPPacketRateCtx {} - -impl RTPPacketRateCtx { - pub fn new() -> RTPPacketRateCtx { - unsafe { - let mut ptr = std::mem::MaybeUninit::uninit(); - ffi::gst_rtp_packet_rate_ctx_reset(ptr.as_mut_ptr(), -1); - RTPPacketRateCtx(Box::new(ptr.assume_init())) - } - } - - pub fn reset(&mut self, clock_rate: i32) { - unsafe { ffi::gst_rtp_packet_rate_ctx_reset(&mut *self.0, clock_rate) } - } - - pub fn update(&mut self, seqnum: u16, ts: u32) -> u32 { - unsafe { ffi::gst_rtp_packet_rate_ctx_update(&mut *self.0, seqnum, ts) } - } - - pub fn get_max_dropout(&mut self, time_ms: i32) -> u32 { - unsafe { ffi::gst_rtp_packet_rate_ctx_get_max_dropout(&mut *self.0, time_ms) } - } - - pub fn get_max_disorder(&mut self, time_ms: i32) -> u32 { - unsafe { ffi::gst_rtp_packet_rate_ctx_get_max_disorder(&mut *self.0, time_ms) } - } -} - -impl Default for RTPPacketRateCtx { - fn default() -> Self { - RTPPacketRateCtx::new() - } -} - -#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)] -pub enum RTPJitterBufferMode { - r#None, - Slave, - Buffer, - Synced, - __Unknown(i32), -} - -impl RTPJitterBuffer { - pub fn new() -> RTPJitterBuffer { - unsafe { from_glib_full(ffi::rtp_jitter_buffer_new()) } - } - - pub fn get_mode(&self) -> RTPJitterBufferMode { - unsafe { from_glib(ffi::rtp_jitter_buffer_get_mode(self.to_glib_none().0)) } - } - - pub fn set_mode(&self, mode: RTPJitterBufferMode) { - unsafe { ffi::rtp_jitter_buffer_set_mode(self.to_glib_none().0, mode.to_glib()) } - } - - pub fn get_delay(&self) -> gst::ClockTime { - unsafe { from_glib(ffi::rtp_jitter_buffer_get_delay(self.to_glib_none().0)) } - } - - pub fn set_delay(&self, delay: gst::ClockTime) { - unsafe { ffi::rtp_jitter_buffer_set_delay(self.to_glib_none().0, delay.to_glib()) } - } - - pub fn set_clock_rate(&self, clock_rate: u32) { - unsafe { ffi::rtp_jitter_buffer_set_clock_rate(self.to_glib_none().0, clock_rate) } - } - - pub fn get_clock_rate(&self) -> u32 { - unsafe { ffi::rtp_jitter_buffer_get_clock_rate(self.to_glib_none().0) } - } - - pub fn calculate_pts( - &self, - dts: gst::ClockTime, - estimated_dts: bool, - rtptime: u32, - base_time: gst::ClockTime, - gap: i32, - is_rtx: bool, - ) -> gst::ClockTime { - unsafe { - let pts = ffi::rtp_jitter_buffer_calculate_pts( - self.to_glib_none().0, - dts.to_glib(), - estimated_dts.to_glib(), - rtptime, - base_time.to_glib(), - gap, - is_rtx.to_glib(), - ); - - if pts == gst_ffi::GST_CLOCK_TIME_NONE { - gst::CLOCK_TIME_NONE - } else { - pts.into() - } - } - } - - pub fn insert(&self, mut item: RTPJitterBufferItem) -> (bool, bool, i32) { - unsafe { - let mut head = mem::MaybeUninit::uninit(); - let mut percent = mem::MaybeUninit::uninit(); - let box_ = item.0.take().expect("Invalid wrapper"); - let ptr = Box::into_raw(box_); - let ret: bool = from_glib(ffi::rtp_jitter_buffer_insert( - self.to_glib_none().0, - ptr, - head.as_mut_ptr(), - percent.as_mut_ptr(), - )); - if !ret { - item.0 = Some(Box::from_raw(ptr)); - } - (ret, from_glib(head.assume_init()), percent.assume_init()) - } - } - - pub fn find_earliest(&self) -> (gst::ClockTime, u32) { - unsafe { - let mut pts = mem::MaybeUninit::uninit(); - let mut seqnum = mem::MaybeUninit::uninit(); - - ffi::rtp_jitter_buffer_find_earliest( - self.to_glib_none().0, - pts.as_mut_ptr(), - seqnum.as_mut_ptr(), - ); - let pts = pts.assume_init(); - let seqnum = seqnum.assume_init(); - - if pts == gst_ffi::GST_CLOCK_TIME_NONE { - (gst::CLOCK_TIME_NONE, seqnum) - } else { - (pts.into(), seqnum) - } - } - } - - pub fn pop(&self) -> (RTPJitterBufferItem, i32) { - unsafe { - let mut percent = mem::MaybeUninit::uninit(); - let item = ffi::rtp_jitter_buffer_pop(self.to_glib_none().0, percent.as_mut_ptr()); - - ( - RTPJitterBufferItem(Some(Box::from_raw(item))), - percent.assume_init(), - ) - } - } - - pub fn peek(&self) -> (gst::ClockTime, u32) { - unsafe { - let item = ffi::rtp_jitter_buffer_peek(self.to_glib_none().0); - if item.is_null() { - (gst::CLOCK_TIME_NONE, std::u32::MAX) - } else { - ((*item).pts.into(), (*item).seqnum) - } - } - } - - pub fn flush(&self) { - unsafe extern "C" fn free_item(item: glib_ffi::gpointer, _: glib_ffi::gpointer) { - let _ = RTPJitterBufferItem(Some(Box::from_raw(item as *mut _))); - } - - unsafe { - ffi::rtp_jitter_buffer_flush(self.to_glib_none().0, Some(free_item)); - } - } - - pub fn reset_skew(&self) { - unsafe { ffi::rtp_jitter_buffer_reset_skew(self.to_glib_none().0) } - } -} - -impl Default for RTPJitterBuffer { - fn default() -> Self { - RTPJitterBuffer::new() - } -}