Skip to main content

viser_ffmpeg/
cache.rs

1use std::collections::HashMap;
2use std::sync::Arc;
3use tokio::sync::RwLock;
4
5use crate::{ProbeResult, probe};
6
7/// Thread-safe probe result cache to avoid redundant ffprobe calls.
8#[derive(Debug, Clone)]
9pub struct ProbeCache {
10    cache: Arc<RwLock<HashMap<String, ProbeResult>>>,
11    engine: ProbeEngine,
12}
13
14/// Backend used to probe media files.
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum ProbeEngine {
17    /// Probe via the `ffprobe` binary.
18    Ffprobe,
19    /// Probe via the in-process `revelo` parser (requires the `revelo` feature).
20    #[cfg(feature = "revelo")]
21    Revelo,
22}
23
24impl ProbeCache {
25    /// Creates an empty cache backed by the `ffprobe` engine.
26    pub fn new() -> Self {
27        Self { cache: Arc::default(), engine: ProbeEngine::Ffprobe }
28    }
29
30    /// Creates an empty cache backed by the `revelo` engine.
31    #[cfg(feature = "revelo")]
32    pub fn with_revelo() -> Self {
33        Self { cache: Arc::default(), engine: ProbeEngine::Revelo }
34    }
35
36    /// Creates an empty cache backed by the given probe engine.
37    pub fn with_engine(engine: ProbeEngine) -> Self {
38        Self { cache: Arc::default(), engine }
39    }
40
41    /// Returns cached result or calls ffprobe and caches the result.
42    pub async fn probe(&self, path: &str) -> anyhow::Result<ProbeResult> {
43        {
44            let cache = self.cache.read().await;
45            if let Some(result) = cache.get(path) {
46                return Ok(result.clone());
47            }
48        }
49
50        let result = match self.engine {
51            ProbeEngine::Ffprobe => probe(path).await?,
52            #[cfg(feature = "revelo")]
53            ProbeEngine::Revelo => crate::probe_revelo(path).await?,
54        };
55
56        {
57            let mut cache = self.cache.write().await;
58            cache.insert(path.to_string(), result.clone());
59        }
60
61        Ok(result)
62    }
63}
64
65impl Default for ProbeCache {
66    fn default() -> Self {
67        Self::new()
68    }
69}