use std::sync::Mutex;
use std::thread::ThreadId;
use super::super::{Config, Encoded};
use super::Backend;
use crate::{Error, Frame};
pub(crate) const NAME: &str = "probe";
pub(crate) type Event = (&'static str, ThreadId);
static LOG: Mutex<Vec<Event>> = Mutex::new(Vec::new());
#[cfg(not(target_os = "macos"))]
static EXCLUSIVE: Mutex<()> = Mutex::new(());
#[cfg(not(target_os = "macos"))]
pub(crate) fn exclusive() -> std::sync::MutexGuard<'static, ()> {
let guard = EXCLUSIVE.lock().unwrap_or_else(|err| err.into_inner());
let _ = take();
guard
}
static GATE: Mutex<()> = Mutex::new(());
#[cfg(not(target_os = "macos"))]
pub(crate) fn hold() -> std::sync::MutexGuard<'static, ()> {
GATE.lock().unwrap_or_else(|err| err.into_inner())
}
fn record(what: &'static str) {
LOG.lock().unwrap().push((what, std::thread::current().id()));
}
#[cfg(not(target_os = "macos"))]
pub(crate) fn take() -> Vec<Event> {
std::mem::take(&mut LOG.lock().unwrap())
}
pub(crate) struct Probe {
pending: Option<Encoded>,
}
impl Probe {
pub(crate) fn open(_config: &Config) -> Result<Box<dyn Backend>, Error> {
record("open");
Ok(Box::new(Self { pending: None }))
}
}
impl Backend for Probe {
fn encode(&mut self, frame: &Frame, _keyframe: bool) -> Result<Vec<Encoded>, Error> {
drop(GATE.lock().unwrap_or_else(|err| err.into_inner()));
record("encode");
let payload = bytes::Bytes::from(frame.timestamp.as_micros().to_string());
let previous = self.pending.replace(Encoded::new(payload, frame.timestamp));
Ok(previous.into_iter().collect())
}
fn flush(&mut self) -> Result<Vec<Encoded>, Error> {
record("flush");
Ok(self.pending.take().into_iter().collect())
}
fn finish(&mut self) -> Result<Vec<Encoded>, Error> {
record("finish");
Ok(self.pending.take().into_iter().collect())
}
fn set_bitrate(&mut self, _bitrate: u64) -> Result<(), Error> {
record("set_bitrate");
Ok(())
}
fn name(&self) -> &str {
NAME
}
}
impl Drop for Probe {
fn drop(&mut self) {
record("drop");
}
}