Skip to main content

ffcine_ingest/
lib.rs

1//! Card offload and the clip catalog, with no GPU or libav dependency so it runs on the Mac in
2//! the van: [`ingest()`] copies camera cards with BLAKE3 verification, a manifest and an
3//! optional backup; [`clock`] applies per-camera clock/zone fixes and flags disagreeing clocks;
4//! [`catalog`] indexes clips with format and picture profile (`docs/ingest.md`).
5
6pub mod camera;
7pub mod catalog;
8pub mod clock;
9pub mod ingest;
10pub mod stats;
11pub mod time;
12
13use std::path::{Path, PathBuf};
14
15pub use catalog::{Catalog, CatalogOptions, Clip, Histogram};
16pub use clock::{ClockConfig, ClockIssue};
17pub use ingest::{Event, IngestOptions, IngestReport, ingest};
18pub use time::{Shift, WallTime, Zone};
19
20#[derive(Debug, thiserror::Error)]
21#[non_exhaustive]
22pub enum Error {
23    #[error("{path}: {source}")]
24    Io {
25        path: PathBuf,
26        source: std::io::Error,
27    },
28    #[error("{path}: copy does not match the card (blake3 {want}, copy has {got})")]
29    Verify {
30        path: PathBuf,
31        want: String,
32        got: String,
33    },
34    #[error("{0}")]
35    Config(String),
36    #[error(transparent)]
37    Json(#[from] serde_json::Error),
38    #[error(transparent)]
39    Core(#[from] ffcine_core::Error),
40}
41
42impl Error {
43    pub(crate) fn io(path: impl AsRef<Path>, source: std::io::Error) -> Self {
44        Self::Io {
45            path: path.as_ref().to_owned(),
46            source,
47        }
48    }
49}
50
51pub type Result<T, E = Error> = std::result::Result<T, E>;
52
53/// Now, UTC.
54pub fn now_utc() -> WallTime {
55    let s = std::time::SystemTime::now()
56        .duration_since(std::time::UNIX_EPOCH)
57        .map_or(0, |d| d.as_secs());
58    WallTime(i64::try_from(s).unwrap_or_default())
59}