use crate::{define::CESStreamInfo, sys::*, util::SlicePack};
use cyberex::{void::*, xself::*};
use std::{ffi::CString, marker::PhantomPinned, pin::Pin};
use anyhow::{bail, Result};
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::<TsMuxer>(user.cast());
p.tsBuf.push(SlicePack {
ptr: HyVoidConst::from_ptr(data.cast()),
size: len as usize,
});
}
pub struct TsMuxer {
ts: HyVoid<()>,
tsBuf: Vec<SlicePack>,
_pin: PhantomPinned,
}
impl TsMuxer {
pub fn new() -> Pin<Box<Self>> {
let mut pin_obj = Box::pin(Self {
ts: HyVoid::from_ptr(unsafe { lcTsMCreate() }),
tsBuf: Vec::new(),
_pin: PhantomPinned,
});
let this = unsafe { self_mut_from_pinbox(&mut pin_obj) };
unsafe {
lcTsMInit(this.ts.as_ptr(), Some(comCb), HyVoid::from_ref(this).as_ptr());
}
pin_obj
}
pub fn enable_time_stamp(self: &mut Pin<Box<Self>>) {
let this = unsafe { self_mut_from_pinbox(self) };
let data = r#"
{
"use_time_stamp": true
}"#;
let config = CString::new(data).unwrap();
unsafe {
lcTsMConfig(
this.ts.as_ptr(),
config.as_bytes().as_ptr() as _,
config.as_bytes().len() as _,
);
}
}
pub fn reset(self: &mut Pin<Box<Self>>) {
let this = unsafe { self_mut_from_pinbox(self) };
unsafe {
lcTsMReset(this.ts.as_ptr());
}
}
pub fn write<'a>(self: &'a mut Pin<Box<Self>>, data: &[u8], info: &CESStreamInfo) -> Result<Vec<&'a [u8]>> {
let this = unsafe { self_mut_from_pinbox(self) };
let ok = unsafe { lcTsMInputData(this.ts.as_ptr(), data.as_ptr(), data.len() as _, info as *const _) };
if ok == 0 {
bail!("Continue")
}
let mut v = Vec::new();
for pack in &this.tsBuf {
v.push(unsafe { std::slice::from_raw_parts(pack.ptr.as_ptr().cast(), pack.size) });
}
this.tsBuf.clear();
Ok(v)
}
}
impl Drop for TsMuxer {
fn drop(&mut self) {
unsafe {
lcTsMDestroy(self.ts.as_ptr());
}
}
}