long_screen/lib.rs
1//! Long Screen as a native library: a screen recording in, one big screenshot out.
2//!
3//! [`run`] drives the same engine the web page runs, pass by pass and in the same order — scan, solve, render,
4//! reveal, framing, preview pyramid — over a [`FrameSource`] (a video file decoded natively by `VideoSource`, or
5//! RGBA frames you already have). It keeps the rows the page would keep in IndexedDB in an in-memory [`Store`],
6//! formats diagnostics with the page's own zh/en catalogue, reports progress and diagnostics to an [`Observer`], and
7//! honours pause and stop through a [`Control`] between steps. The [`RunResult`] holds the canvases (the print, its
8//! framed presentation and any separate fragments) as tiles, and writes any of them as a PNG of any size, streamed
9//! band by band.
10//!
11//! The command-line tool `long-screen` (feature `cli`) is a thin layer over this crate; a desktop app or a Python
12//! binding can drive it the same way.
13//!
14//! ```no_run
15//! use long_screen::{run, Control, DecodeOptions, Options, VideoSource};
16//!
17//! let mut source = VideoSource::open("recording.mov".as_ref(), DecodeOptions::default())?;
18//! let control = Control::new(); // clone it to another thread to pause or stop the run
19//! let mut on_progress = |p: &long_screen::Progress| eprintln!("{} {:.0}%", p.phase, p.fraction * 100.0);
20//! let result = run(&mut source, &Options::default(), &mut on_progress, &control)?;
21//! if let Some(print) = result.print() {
22//! let file = std::fs::File::create("print.png")?;
23//! result.write_png(&print.id, std::io::BufWriter::new(file))?;
24//! }
25//! for d in result.diagnostics() {
26//! eprintln!("{} {}: {}", d.severity, d.code, d.message);
27//! }
28//! # Ok::<(), Box<dyn std::error::Error>>(())
29//! ```
30//!
31//! # Layers
32//!
33//! The crate root is the driver API. Under it sit the layers the driver, the web page's WebAssembly and the
34//! benchmarks are built from. They are public so those builds can reach them, but they are implementation layers:
35//! their API follows what those hosts need and may change in minor versions.
36//!
37//! - [`kernels`]: the reconstruction algorithms (motion, regions and layers, tracking, the pose graph, compositing,
38//! reveal, framing, the preview pyramid, YUV→RGBA), with no I/O. Compiles for `wasm32-unknown-unknown`.
39//! - [`engine`]: one run as a state machine over the kernels, driven step by step by a host that stores the rows.
40//! Compiles for `wasm32-unknown-unknown`.
41//! - `decode` (feature `decode`): native video decoding with the system decoder or a user-installed ffmpeg.
42//!
43//! # Features
44//!
45//! - `driver` (default): the driver API at the crate root ([`run`], [`Options`], [`RunResult`], the sources, the
46//! in-memory [`Store`]). Implies `catalog`.
47//! - `decode` (default): the `decode` module and `VideoSource` (AVFoundation on macOS, Media Foundation on Windows,
48//! ffmpeg everywhere). Re-exports its options as `DecodeOptions` and `DecodeBackend`.
49//! - `rayon` (default): the kernels run on rayon's thread pool. Results do not depend on the thread count.
50//! - `catalog` (default): the embedded zh/en diagnostic and progress catalogue and its formatter
51//! (`engine::catalog`), which reproduces the web page's messages exactly.
52//! - `cli` (default): the `long-screen` command line and its argument parser. Implies `driver` and `decode`.
53//!
54//! With `default-features = false` only [`kernels`] and [`engine`] remain, which is what the web page's
55//! WebAssembly builds.
56
57// The threaded WebAssembly build is compiled with RUSTC_BOOTSTRAP for -Zbuild-std; wait/notify are still unstable
58// there (kernels::pool).
59#![cfg_attr(target_feature = "atomics", feature(stdarch_wasm_atomic_wait))]
60// The crate docs above link the driver's items, which a build without the `driver` feature does not have.
61#![cfg_attr(not(feature = "driver"), allow(rustdoc::broken_intra_doc_links))]
62
63#[cfg(feature = "decode")]
64pub mod decode;
65pub mod engine;
66pub mod kernels;
67
68#[cfg(feature = "driver")]
69mod context;
70#[cfg(feature = "driver")]
71mod driver;
72#[cfg(feature = "driver")]
73mod output;
74#[cfg(feature = "driver")]
75mod present;
76#[cfg(feature = "driver")]
77mod render;
78#[cfg(feature = "driver")]
79mod reveal;
80#[cfg(feature = "driver")]
81mod scan;
82#[cfg(feature = "driver")]
83mod solve;
84#[cfg(feature = "driver")]
85pub mod source;
86#[cfg(feature = "driver")]
87pub mod store;
88#[cfg(feature = "driver")]
89mod tiles;
90#[cfg(feature = "driver")]
91pub mod value;
92
93#[cfg(feature = "decode")]
94pub use decode::{Backend as DecodeBackend, Options as DecodeOptions};
95#[cfg(feature = "driver")]
96pub use driver::*;
97
98// The crate README's examples, compiled by `cargo test --doc`.
99#[cfg(all(doctest, feature = "driver", feature = "decode"))]
100#[doc = include_str!("../README.md")]
101pub struct ReadmeDoctests;