use std::env;
use std::process::ExitCode;
use std::sync::atomic::{AtomicI64, AtomicUsize, Ordering};
use std::time::{Duration, Instant};
use librtmp2::client::Client;
use librtmp2::types::*;
static VIDEO_FRAMES: AtomicI64 = AtomicI64::new(0);
static AUDIO_FRAMES: AtomicI64 = AtomicI64::new(0);
static TOTAL_BYTES: AtomicUsize = AtomicUsize::new(0);
fn on_frame(frame: &Frame) {
if !frame.data.is_null() && frame.size > 0 {
let payload = unsafe { std::slice::from_raw_parts(frame.data, frame.size as usize) };
let sum: u64 = payload.iter().map(|&b| b as u64).sum();
std::hint::black_box(sum);
}
TOTAL_BYTES.fetch_add(frame.size as usize, Ordering::SeqCst);
match frame.frame_type {
FrameType::Video => VIDEO_FRAMES.fetch_add(1, Ordering::SeqCst),
FrameType::Audio => AUDIO_FRAMES.fetch_add(1, Ordering::SeqCst),
_ => 0,
};
}
fn main() -> ExitCode {
let args: Vec<String> = env::args().collect();
let url = args
.get(1)
.cloned()
.unwrap_or_else(|| "rtmp://127.0.0.1:1935/live/test".to_string());
let timeout_s: u64 = args.get(2).and_then(|s| s.parse().ok()).unwrap_or(25);
let mut client = Client::new();
client.on_frame_cb = Some(on_frame);
println!("[interop-play] connecting to {url}");
if client.connect(&url).is_err() {
eprintln!("[interop-play] connect failed");
return ExitCode::from(1);
}
if client.play().is_err() {
eprintln!("[interop-play] play failed");
return ExitCode::from(1);
}
println!("[interop-play] play started, pumping frames");
let deadline = Instant::now() + Duration::from_secs(timeout_s);
let mut success = false;
while Instant::now() < deadline {
if let Err(e) = client.poll(200) {
eprintln!("[interop-play] poll error {e:?}");
break;
}
if VIDEO_FRAMES.load(Ordering::SeqCst) > 0 && AUDIO_FRAMES.load(Ordering::SeqCst) > 0 {
success = true;
break;
}
}
let video = VIDEO_FRAMES.load(Ordering::SeqCst);
let audio = AUDIO_FRAMES.load(Ordering::SeqCst);
let bytes = TOTAL_BYTES.load(Ordering::SeqCst);
success |= video > 0 && audio > 0;
println!("[interop-play] video={video} audio={audio} bytes={bytes}");
if success {
println!("[interop-play] PASS: pulled video and audio from real RTMP server");
return ExitCode::SUCCESS;
}
eprintln!("[interop-play] FAIL: timed out (video={video} audio={audio})");
ExitCode::from(2)
}