use crate::{define::CESStreamInfo, sys::*, util::SlicePack};
use anyhow::{bail, Result};
use cyberex::{void::*, xself::*};
use std::{marker::PhantomPinned, pin::Pin};
unsafe extern "C" fn comCb(
data: *const ::std::os::raw::c_uchar,
len: ::std::os::raw::c_int,
user: *mut ::std::os::raw::c_void,
) {
let p = opacue_to_mut::<RtpMuxer>(user.cast());
p.buf.push(SlicePack {
ptr: HyVoidConst::from_ptr(data.cast()),
size: len as usize,
});
}
pub struct RtpMuxer {
ptr: HyVoid<()>,
buf: Vec<SlicePack>,
_pin: PhantomPinned,
}
impl RtpMuxer {
pub fn new() -> Pin<Box<Self>> {
let mut pin_obj = Box::pin(Self {
ptr: HyVoid::from_ptr(unsafe { lcRtpMCreate() }),
buf: Vec::new(),
_pin: PhantomPinned,
});
let this = unsafe { self_mut_from_pinbox(&mut pin_obj) };
unsafe {
lcRtpMInit(this.ptr.as_ptr(), Some(comCb), 0, HyVoid::from_ref(this).as_ptr());
}
pin_obj
}
pub fn write<'a>(self: &'a mut Pin<Box<Self>>, data: &[u8], info: Option<CESStreamInfo>) -> Result<Vec<&'a [u8]>> {
let this = unsafe { self_mut_from_pinbox(self) };
this.buf.clear();
let ok = unsafe {
lcRtpMInputData(
this.ptr.as_ptr(),
data.as_ptr(),
data.len() as _,
if let Some(info) = &info {
info as *const _
} else {
std::ptr::null()
},
)
};
if ok == 0 {
bail!("Error Occur")
}
let mut v = Vec::new();
for pack in &this.buf {
v.push(unsafe { std::slice::from_raw_parts(pack.ptr.as_ptr().cast(), pack.size) });
}
this.buf.clear();
Ok(v)
}
pub fn get_init_data(self: &Pin<Box<Self>>) -> Result<Vec<u8>> {
let this = self_from_pinbox(self);
let mut initData = vec![0; 1024 * 8];
let real_len = unsafe { lcRtpMGetInitData(this.ptr.as_ptr(), initData.as_mut_ptr(), initData.len() as _) };
initData.resize(real_len as _, 0);
if initData.is_empty() {
bail!("Continue input data");
}
Ok(initData)
}
}
impl Drop for RtpMuxer {
fn drop(&mut self) {
unsafe {
lcRtpMDestroy(self.ptr.as_ptr());
}
}
}