openipc-video 0.1.40

Low-latency platform video decoding for OpenIPC applications
Documentation
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
    use std::{
        env, fs, thread,
        time::{Duration, Instant},
    };

    use openipc_video::{
        DecoderOptions, EncodedAccessUnit, PlatformDecoder, VideoCodec, VideoDecoder,
        VideoTimestamp,
    };

    let mut args = env::args().skip(1);
    let codec =
        match args.next().as_deref() {
            Some("h264") => VideoCodec::H264,
            Some("h265") | Some("hevc") => VideoCodec::H265,
            _ => return Err(
                "usage: decode_access_unit <h264|h265> <annex-b-access-unit> [--allow-software]"
                    .into(),
            ),
        };
    let path = args
        .next()
        .ok_or("usage: decode_access_unit <h264|h265> <annex-b-access-unit> [--allow-software]")?;
    let allow_software = args.any(|argument| argument == "--allow-software");
    let data = fs::read(path)?;
    let capabilities = PlatformDecoder::probe_capabilities();
    println!("capabilities={capabilities:?}");
    let mut decoder = PlatformDecoder::new(DecoderOptions {
        require_hardware: !allow_software,
        ..DecoderOptions::default()
    })?;
    let outcome = decoder.submit(EncodedAccessUnit::new(
        codec,
        data,
        VideoTimestamp::from_rtp(0),
        true,
    ))?;
    println!("submit={outcome:?}");

    let deadline = Instant::now() + Duration::from_secs(1);
    while Instant::now() < deadline {
        if let Some(frame) = decoder.latest_frame() {
            let dimensions = frame.dimensions();
            println!(
                "decoded={}x{} pixel_format={:?}",
                dimensions.width,
                dimensions.height,
                openipc_video::DecodedSurface::pixel_format(&frame.surface),
            );
            #[cfg(target_os = "macos")]
            println!("iosurface={}", frame.surface.is_io_surface_backed());
            #[cfg(target_os = "linux")]
            println!(
                "drm_fourcc={:#010x} pitches={:?}",
                frame.surface.drm_fourcc(),
                frame.surface.plane_pitches()
            );
            #[cfg(target_os = "windows")]
            println!(
                "d3d11_subresource={} texture={:?}",
                frame.surface.subresource_index(),
                frame.surface.texture()
            );
            return Ok(());
        }
        thread::sleep(Duration::from_millis(2));
    }
    Err(format!("no decoded frame; stats={:?}", decoder.stats()).into())
}

#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
fn main() {
    eprintln!("decode_access_unit supports macOS, Linux, and Windows");
}