use gstreamer::{Caps, ClockTime, StructureRef};
use strum_macros::Display;
use wayclip_core::models::error::WayclipError;
#[derive(Clone, Debug, Display, PartialEq, Eq)]
pub enum ContentType {
#[strum(serialize = "video")]
Video,
#[strum(serialize = "audio")]
Audio,
}
#[derive(Debug, Clone)]
pub struct EncodedFrame {
pub payload: gstreamer::Buffer,
pub pts: ClockTime,
pub dts: Option<ClockTime>,
pub duration: Option<ClockTime>,
pub is_keyframe: bool,
}
impl EncodedFrame {
pub fn new(
payload: gstreamer::Buffer,
pts: ClockTime,
dts: Option<ClockTime>,
duration: Option<ClockTime>,
is_keyframe: bool,
) -> Self {
Self {
payload,
pts,
dts,
duration,
is_keyframe,
}
}
}
impl EncodedFrame {
pub fn compact(buf: &gstreamer::BufferRef) -> gstreamer::Buffer {
let Ok(map) = buf.map_readable() else {
return buf.to_owned();
};
let mut out = gstreamer::Buffer::from_slice(map.as_slice().to_vec());
if let Some(o) = out.get_mut() {
o.set_pts(buf.pts());
o.set_dts(buf.dts());
o.set_duration(buf.duration());
o.set_offset(buf.offset());
o.set_offset_end(buf.offset_end());
o.set_flags(buf.flags());
}
out
}
}
#[derive(Clone, Debug)]
pub struct SaveData {
pub video_frames: Vec<EncodedFrame>,
pub audio_frames: Vec<EncodedFrame>,
pub video_caps: gstreamer::Caps,
pub audio_caps: Option<gstreamer::Caps>,
pub duration: ClockTime,
}
impl SaveData {
pub fn get_base_pts(&self) -> (ClockTime, ClockTime) {
(
self.video_frames
.first()
.map(|frame| frame.pts)
.unwrap_or(gstreamer::ClockTime::ZERO),
self.audio_frames
.first()
.map(|frame| frame.pts)
.unwrap_or(gstreamer::ClockTime::ZERO),
)
}
pub fn get_video_structure(&self) -> Result<&StructureRef, WayclipError> {
self.video_caps
.structure(0)
.ok_or_else(|| WayclipError::Remux("Video caps has no structure".into()))
}
pub fn get_audio_structure(&self) -> Result<Option<(&Caps, &StructureRef)>, WayclipError> {
match (&self.audio_caps, self.audio_frames.is_empty()) {
(Some(caps), false) => Ok(Some((
caps,
caps.structure(0)
.ok_or_else(|| WayclipError::NotFound("No structure found".into()))?,
))),
_ => Ok(None),
}
}
pub fn clear_caps(&self, caps: Caps) -> Caps {
let mut builder = Caps::builder_full();
for structure in caps.iter() {
builder = builder.structure(structure.to_owned());
}
builder.build()
}
pub fn get_bytes(&self) -> (u64, u64) {
(
self.video_frames
.iter()
.map(|f| f.payload.size() as u64)
.sum::<u64>(),
self.audio_frames
.iter()
.map(|f| f.payload.size() as u64)
.sum::<u64>(),
)
}
}