use std::collections::HashMap;
use std::sync::Arc;
use multimux::origin::{AppState, router};
use multimux::pipeline::{MockSource, run_pipeline};
use multimux::store::StreamStore;
use transmux::avc_config_from_sprop;
use transmux::pipeline::{CodecConfig, Sample, TrackSpec};
const SPROP: &str = "Z0IAKeKQFAe2AtwEBAaQeJEV,aM48gA==";
const VIDEO_TIMESCALE: u32 = 90_000;
const FRAME_DUR: u32 = VIDEO_TIMESCALE / 30;
const FRAME_COUNT: u32 = 120;
const SYNC_INTERVAL_FRAMES: u32 = 30;
const TARGET_DURATION_SECS: f64 = 1.0;
const PART_TARGET_MS: u32 = 500;
const WINDOW_SEGMENTS: usize = 8;
const STREAM_NAME: &str = "cam";
#[tokio::main]
async fn main() {
let config = avc_config_from_sprop(SPROP).expect("valid sprop");
let specs = vec![TrackSpec::new(
1,
VIDEO_TIMESCALE,
CodecConfig::Avc {
config,
width: 0,
height: 0,
},
)];
let mut batches = Vec::new();
for i in 0..FRAME_COUNT {
let is_sync = i % SYNC_INTERVAL_FRAMES == 0;
let data = vec![0xAAu8.wrapping_add((i % 251) as u8); 64];
let sample = Sample::new(data, FRAME_DUR, is_sync, 0);
batches.push(vec![(1u32, sample)]);
}
let store = Arc::new(StreamStore::new(
TARGET_DURATION_SECS,
PART_TARGET_MS,
WINDOW_SEGMENTS,
));
let source = MockSource::new(specs, batches);
run_pipeline(store.clone(), TARGET_DURATION_SECS, PART_TARGET_MS, source)
.await
.expect("mock pipeline runs to completion");
let mut streams = HashMap::new();
streams.insert(STREAM_NAME.to_string(), store);
let app = router(Arc::new(AppState { streams }));
let listener = tokio::net::TcpListener::bind("127.0.0.1:0")
.await
.expect("bind ephemeral localhost port");
let addr = listener.local_addr().expect("listener has a local address");
println!("multimux serve_mock: http://{addr}/{STREAM_NAME}/master.m3u8");
axum::serve(listener, app).await.expect("axum server");
}