viser_contextaware/
lib.rs1mod profile;
8
9pub use profile::*;
10
11use serde::{Deserialize, Serialize};
12use std::time::{Duration, Instant};
13use viser_encoding::{Config as EncodingConfig, ProgressSender};
14use viser_hull::{Hull, Point};
15use viser_ladder::{self, Ladder};
16
17#[derive(Debug, Clone)]
19pub struct Config {
20 pub profiles: Vec<Profile>,
22 pub crf_values: Vec<i32>,
24 pub preset: String,
26 pub subsample: i32,
28 pub parallel: i32,
30}
31
32impl Default for Config {
33 fn default() -> Self {
34 Self {
35 profiles: all_profiles(),
36 crf_values: vec![18, 22, 26, 30, 34, 38, 42],
37 preset: "veryfast".into(),
38 subsample: 5,
39 parallel: 2,
40 }
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct DeviceResult {
47 pub profile: Profile,
49 pub hull: Hull,
51 pub ladder: Ladder,
53 pub points: Vec<Point>,
55 pub trial_count: usize,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct Result {
62 pub source: String,
64 pub devices: Vec<DeviceResult>,
66 pub duration: Duration,
68}
69
70#[derive(Debug, Clone)]
72pub struct Progress {
73 pub device_done: usize,
75 pub device_total: usize,
77 pub device_name: String,
79}
80
81pub async fn analyze(
83 source: &str,
84 cfg: Config,
85 progress_tx: Option<tokio::sync::mpsc::Sender<Progress>>,
86) -> anyhow::Result<Result> {
87 let start = Instant::now();
88 let mut devices = Vec::new();
89 let sender = ProgressSender::new(progress_tx);
90
91 for (i, profile) in cfg.profiles.iter().enumerate() {
92 let pt_cfg = viser_pertitle::Config {
93 encoding: EncodingConfig {
94 resolutions: profile.resolutions.clone(),
95 crf_values: cfg.crf_values.clone(),
96 codecs: profile.codecs.clone(),
97 preset: cfg.preset.clone(),
98 subsample: cfg.subsample,
99 parallel: cfg.parallel,
100 ..Default::default()
101 },
102 ladder_opts: profile.ladder_opts.clone(),
103 vmaf_model: profile.vmaf_model.clone(),
104 checkpoint_path: String::new(),
105 allow_hdr: false,
106 };
107
108 let pt_result = viser_pertitle::analyze(source, pt_cfg, None)
109 .await
110 .map_err(|e| anyhow::anyhow!("analysis for {} failed: {e}", profile.name))?;
111
112 let device_ladder = viser_ladder::select(&pt_result.hull, &profile.ladder_opts);
113
114 devices.push(DeviceResult {
115 profile: profile.clone(),
116 hull: pt_result.hull,
117 ladder: device_ladder,
118 points: pt_result.points,
119 trial_count: pt_result.trial_count,
120 });
121
122 sender.send(Progress {
123 device_done: i + 1,
124 device_total: cfg.profiles.len(),
125 device_name: profile.name.clone(),
126 });
127 }
128
129 Ok(Result { source: source.to_string(), devices, duration: start.elapsed() })
130}