use clap::Subcommand;
use hang::moq_net;
use moq_mux::import;
#[derive(Subcommand, Clone)]
pub enum PublishFormat {
Avc3,
Fmp4,
Hls {
#[arg(long)]
playlist: String,
},
}
enum PublishDecoder {
Avc3(Box<import::Avc3>),
Fmp4(Box<import::Fmp4>),
Hls(Box<import::Hls>),
}
impl PublishDecoder {
fn decode_buf(&mut self, buffer: &mut bytes::BytesMut) -> anyhow::Result<()> {
match self {
Self::Avc3(d) => d.decode_stream(buffer, None),
Self::Fmp4(d) => d.decode(buffer),
Self::Hls(_) => unreachable!(),
}
}
}
pub struct Publish {
decoder: PublishDecoder,
broadcast: moq_net::BroadcastProducer,
}
impl Publish {
pub fn new(format: &PublishFormat) -> anyhow::Result<Self> {
let mut broadcast = moq_net::Broadcast::new().produce();
let catalog = moq_mux::catalog::Producer::new(&mut broadcast)?;
let decoder = match format {
PublishFormat::Avc3 => {
let avc3 = import::Avc3::new(broadcast.clone(), catalog.clone());
PublishDecoder::Avc3(Box::new(avc3))
}
PublishFormat::Fmp4 => {
let fmp4 = import::Fmp4::new(broadcast.clone(), catalog.clone());
PublishDecoder::Fmp4(Box::new(fmp4))
}
PublishFormat::Hls { playlist } => {
let hls = import::Hls::new(
broadcast.clone(),
catalog.clone(),
import::HlsConfig::new(playlist.clone()),
)?;
PublishDecoder::Hls(Box::new(hls))
}
};
Ok(Self { decoder, broadcast })
}
pub fn consume(&self) -> moq_net::BroadcastConsumer {
self.broadcast.consume()
}
pub async fn run(mut self) -> anyhow::Result<()> {
if let PublishDecoder::Hls(decoder) = &mut self.decoder {
decoder.init().await?;
decoder.run().await
} else {
let mut stdin = tokio::io::stdin();
let mut buffer = bytes::BytesMut::new();
loop {
let n = tokio::io::AsyncReadExt::read_buf(&mut stdin, &mut buffer).await?;
if n == 0 {
return Ok(());
}
self.decoder.decode_buf(&mut buffer)?;
}
}
}
}