use std::mem::replace;
use anyhow::{Result, bail};
use cyberex::ipp;
use crate::{define::IndexPacket, packet::PacketEs};
pub type Cache = Vec<IndexPacket>;
pub struct Gops {
cache: Cache,
index: usize,
gop_size: usize,
gop_max: usize,
is_last_key: bool,
}
impl Gops {
pub fn new(gop_max: usize) -> Self {
Self {
cache: Vec::new(),
index: 0,
gop_size: 0,
gop_max,
is_last_key: false,
}
}
pub fn input_data(&mut self, payload: Vec<PacketEs>, is_key: bool) -> Result<IndexPacket> {
if payload.is_empty() {
bail!("Payload is empty")
}
let index = ipp!(self.index);
let pkt = IndexPacket { payload, index };
let is_gop_start = self.is_gop_start(is_key);
let gop_cache = &mut self.cache;
if is_gop_start {
if !gop_cache.is_empty() && self.gop_size == self.gop_max {
gop_cache.clear();
self.gop_size = 0;
}
self.gop_size += 1;
Self::input_cache(gop_cache, &pkt, is_key, &mut self.is_last_key);
return Ok(pkt);
}
if gop_cache.is_empty() {
bail!("Gop cache is waiting for key frame to start")
}
Self::input_cache(gop_cache, &pkt, is_key, &mut self.is_last_key);
Ok(pkt)
}
fn input_cache(cache: &mut Cache, pkt: &IndexPacket, is_key: bool, is_last_key: &mut bool) {
cache.push(pkt.clone());
let _ = replace(is_last_key, is_key);
}
fn is_gop_start(&self, is_key: bool) -> bool {
is_key && !self.is_last_key
}
pub fn view(&self) -> &Vec<IndexPacket> {
&self.cache
}
}