aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-07-31 16:52:46 +0200
committermetamuffin <metamuffin@disroot.org>2023-07-31 16:52:46 +0200
commit0c651f11920350a4aa96aa24f8fe15b28390aed2 (patch)
tree724e5e79d6c6000077cd0c33c669c32475ed069f
parente6e424833315a6c0d04c7706d539f57e1b1df0f7 (diff)
downloadjellything-0c651f11920350a4aa96aa24f8fe15b28390aed2.tar
jellything-0c651f11920350a4aa96aa24f8fe15b28390aed2.tar.bz2
jellything-0c651f11920350a4aa96aa24f8fe15b28390aed2.tar.zst
update remuxer for new schema
-rw-r--r--common/src/api.rs15
-rw-r--r--remuxer/src/import/mod.rs51
-rw-r--r--remuxer/src/lib.rs59
-rw-r--r--server/src/database.rs6
-rw-r--r--server/src/library.rs27
-rw-r--r--server/src/routes/mod.rs5
-rw-r--r--server/src/routes/ui/account/settings.rs10
7 files changed, 79 insertions, 94 deletions
diff --git a/common/src/api.rs b/common/src/api.rs
deleted file mode 100644
index 27541a2..0000000
--- a/common/src/api.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use crate::{DirectoryInfo, ItemInfo};
-use serde::{Deserialize, Serialize};
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub enum ApiNode {
- Directory {
- identifier: String,
- info: DirectoryInfo,
- children: Vec<String>,
- },
- Item {
- identifier: String,
- info: ItemInfo,
- },
-}
diff --git a/remuxer/src/import/mod.rs b/remuxer/src/import/mod.rs
index 7971c18..4ccbd1c 100644
--- a/remuxer/src/import/mod.rs
+++ b/remuxer/src/import/mod.rs
@@ -4,7 +4,7 @@
Copyright (C) 2023 metamuffin <metamuffin.org>
*/
use anyhow::{anyhow, bail, Result};
-use jellycommon::{BlockIndex, ItemInfo, SeekIndex, SourceTrack, SourceTrackKind};
+use jellycommon::{BlockIndex, LocalTrack, SeekIndex, SourceTrack, SourceTrackKind};
use jellymatroska::{
block::Block,
matroska::MatroskaTag,
@@ -14,7 +14,9 @@ use jellymatroska::{
use log::{debug, error, info, trace, warn};
use std::{collections::HashMap, fs::File, path::PathBuf};
-pub fn import_read(path: &PathBuf, input: &mut EbmlReader, iteminfo: &mut ItemInfo) -> Result<()> {
+pub fn import_read(path: &PathBuf, input: &mut EbmlReader) -> Result<()> {
+ let mut iteminfo = Vec::new();
+ let mut private = Vec::new();
while let Some(item) = input.next() {
let item = match item {
Ok(item) => item,
@@ -43,7 +45,7 @@ pub fn import_read(path: &PathBuf, input: &mut EbmlReader, iteminfo: &mut ItemIn
MatroskaTag::Segment(_) => {
info!("segment start");
let mut children = Unflatten::new_with_end(input, item);
- import_read_segment(path, &mut children, iteminfo)?;
+ import_read_segment(path, &mut children, &mut iteminfo, &mut private)?;
info!("segment end");
}
_ => debug!("(r) tag ignored: {item:?}"),
@@ -56,8 +58,9 @@ pub fn import_read(path: &PathBuf, input: &mut EbmlReader, iteminfo: &mut ItemIn
fn import_read_segment(
path: &PathBuf,
segment: &mut Unflatten,
- iteminfo: &mut ItemInfo,
-) -> Result<()> {
+ iteminfo: &mut Vec<SourceTrack>,
+ private: &mut Vec<LocalTrack>,
+) -> Result<Option<f64>> {
let (mut timestamp_scale, mut duration) = (None, None);
let mut seek_index = HashMap::new();
@@ -142,8 +145,7 @@ fn import_read_segment(
_ => (),
}
}
- let itrack_index = iteminfo.tracks.len();
- let mtrack_index = index.unwrap();
+ let track_index = index.unwrap();
let kind = match kind.ok_or(anyhow!("track type required"))? {
1 => SourceTrackKind::Video {
fps: fps.unwrap_or(0.0), // TODO
@@ -158,19 +160,18 @@ fn import_read_segment(
17 => SourceTrackKind::Subtitles,
_ => bail!("invalid track type"),
};
- iteminfo.tracks.insert(
- itrack_index,
- SourceTrack {
- track_number: mtrack_index,
- path: path.to_owned(),
- default_duration,
- codec_private,
- name: name.unwrap_or_else(|| "unnamed".to_string()),
- codec: codec.unwrap(),
- language: language.unwrap_or_else(|| "none".to_string()),
- kind,
- },
- );
+ iteminfo.push(SourceTrack {
+ default_duration,
+ name: name.unwrap_or_else(|| "unnamed".to_string()),
+ codec: codec.unwrap(),
+ language: language.unwrap_or_else(|| "none".to_string()),
+ kind,
+ });
+ private.push(LocalTrack {
+ track: track_index as usize,
+ path: path.to_owned(),
+ codec_private,
+ })
}
_ => debug!("(rst) tag ignored: {item:?}"),
}
@@ -253,9 +254,9 @@ fn import_read_segment(
bincode::config::standard(),
)?;
}
- if let Some(duration) = duration {
- iteminfo.duration =
- (duration * timestamp_scale.unwrap_or(1_000_000) as f64) / 1_000_000_000_f64;
- }
- Ok(())
+ Ok(if let Some(duration) = duration {
+ Some((duration * timestamp_scale.unwrap_or(1_000_000) as f64) / 1_000_000_000_f64)
+ } else {
+ None
+ })
}
diff --git a/remuxer/src/lib.rs b/remuxer/src/lib.rs
index e531f06..5fc35f8 100644
--- a/remuxer/src/lib.rs
+++ b/remuxer/src/lib.rs
@@ -9,7 +9,7 @@ pub mod trim_writer;
use crate::{segment_extractor::SegmentExtractIter, trim_writer::TrimWriter};
use anyhow::{anyhow, Context};
-use jellycommon::{BlockIndex, ItemInfo, SeekIndex, SourceTrack, SourceTrackKind};
+use jellycommon::{BlockIndex, ItemPublic, LocalTrack, SeekIndex, SourceTrack, SourceTrackKind};
use jellymatroska::{
block::Block,
read::EbmlReader,
@@ -39,11 +39,12 @@ impl RemuxerContext {
writer: impl Write + 'static,
range: Range<usize>,
path_base: PathBuf,
- iteminfo: ItemInfo,
+ item: ItemPublic,
+ track_sources: Vec<LocalTrack>,
selection: Vec<usize>,
webm: bool,
) -> anyhow::Result<()> {
- info!("remuxing {:?} to have tracks {selection:?}", iteminfo.title);
+ info!("remuxing {:?} to have tracks {selection:?}", item.title);
let writer = TrimWriter::new(writer, range.clone());
let mut output = EbmlWriter::new(writer, 0);
@@ -52,6 +53,8 @@ impl RemuxerContext {
reader: EbmlReader,
mapped: u64,
index: SeekIndex,
+ source_track_index: usize,
+ codec_private: Option<Vec<u8>>,
layouting_progress_index: usize,
}
@@ -61,21 +64,21 @@ impl RemuxerContext {
.iter()
.enumerate()
.map(|(index, sel)| {
- let info = iteminfo
+ let info = item
+ .media.as_ref()
+ .unwrap()
.tracks
- .get(sel)
+ .get(*sel)
.ok_or(anyhow!("track not available"))?
.to_owned();
- let source_path = path_base.join(&info.path);
+ let private = &track_sources[*sel];
+ let source_path = path_base.join(&private.path);
let mapped = index as u64 + 1;
- info!(
- "\t- {sel} {source_path:?} ({} => {mapped})",
- info.track_number
- );
+ info!("\t- {sel} {source_path:?} ({} => {mapped})", private.track);
info!("\t {}", info);
let file = File::open(&source_path).context("opening source file")?;
let mut index =
- File::open(source_path.with_extension(format!("si.{}", info.track_number)))
+ File::open(source_path.with_extension(format!("si.{}", private.track)))
.context("opening seek index file")?;
let index = bincode::decode_from_std_read::<SeekIndex, _, _>(
&mut index,
@@ -88,6 +91,8 @@ impl RemuxerContext {
reader,
info,
mapped,
+ source_track_index: private.track,
+ codec_private: private.codec_private.clone(),
layouting_progress_index: 0,
})
})
@@ -115,16 +120,16 @@ impl RemuxerContext {
output.write_tag(&MatroskaTag::Info(Master::Collected(vec![
MatroskaTag::TimestampScale(1_000_000),
- MatroskaTag::Duration(iteminfo.duration * 1000.0),
- MatroskaTag::Title(iteminfo.title.clone()),
+ MatroskaTag::Duration(item.media.unwrap().duration * 1000.0),
+ MatroskaTag::Title(item.title.clone()),
MatroskaTag::MuxingApp("jellyremux".to_string()),
MatroskaTag::WritingApp("jellything".to_string()),
])))?;
output.write_tag(&MatroskaTag::Tags(Master::Collected(vec![])))?;
let tracks_header = inputs
- .iter()
- .map(|rc| track_to_ebml(rc.mapped, &rc.info))
+ .iter_mut()
+ .map(|rc| track_to_ebml(rc.mapped, &rc.info, rc.codec_private.take()))
.collect();
output.write_tag(&MatroskaTag::Tracks(Master::Collected(tracks_header)))?;
@@ -197,7 +202,10 @@ impl RemuxerContext {
info!("segment layout computed ({} clusters)", clusters.len());
clusters
};
- info!("(perf) compute segment layout: {:?}", Instant::now() - timing_cp);
+ info!(
+ "(perf) compute segment layout: {:?}",
+ Instant::now() - timing_cp
+ );
let timing_cp = Instant::now();
let max_cue_size = 4 // cues id
@@ -230,7 +238,9 @@ impl RemuxerContext {
let first_cluster_offset_predict = max_cue_size + output.position();
// make the cluster position relative to the segment start as they should
- segment_layout.iter_mut().for_each(|e| e.position += first_cluster_offset_predict - segment_offset);
+ segment_layout
+ .iter_mut()
+ .for_each(|e| e.position += first_cluster_offset_predict - segment_offset);
output.write_tag(&MatroskaTag::Cues(Master::Collected(
segment_layout
@@ -265,7 +275,9 @@ impl RemuxerContext {
if skip != 0 {
info!("skipping {skip} clusters");
- output.seek(SeekFrom::Start((segment_layout[skip].position + segment_offset) as u64))?;
+ output.seek(SeekFrom::Start(
+ (segment_layout[skip].position + segment_offset) as u64,
+ ))?;
}
struct ReaderD<'a> {
@@ -284,7 +296,8 @@ impl RemuxerContext {
MatroskaTag::Cluster(Master::Start),
)
.context("seeking in input")?;
- let mut stream = SegmentExtractIter::new(&mut inp.reader, inp.info.track_number);
+ let mut stream =
+ SegmentExtractIter::new(&mut inp.reader, inp.source_track_index as u64);
Ok(ReaderD {
mapped: inp.mapped,
@@ -333,7 +346,11 @@ impl RemuxerContext {
}
}
-pub fn track_to_ebml(number: u64, track: &SourceTrack) -> MatroskaTag {
+pub fn track_to_ebml(
+ number: u64,
+ track: &SourceTrack,
+ codec_private: Option<Vec<u8>>,
+) -> MatroskaTag {
let mut els = vec![
MatroskaTag::TrackNumber(number),
MatroskaTag::TrackUID(number),
@@ -372,7 +389,7 @@ pub fn track_to_ebml(number: u64, track: &SourceTrack) -> MatroskaTag {
els.push(MatroskaTag::TrackType(19));
}
}
- if let Some(d) = &track.codec_private {
+ if let Some(d) = &codec_private {
els.push(MatroskaTag::CodecPrivate(d.clone()));
}
MatroskaTag::TrackEntry(Master::Collected(els))
diff --git a/server/src/database.rs b/server/src/database.rs
index b6e9ab9..bfb5d47 100644
--- a/server/src/database.rs
+++ b/server/src/database.rs
@@ -5,6 +5,7 @@
*/
use crate::{routes::ui::account::hash_password, CONF};
use anyhow::Context;
+use jellycommon::SeekIndex;
use log::info;
use serde::{Deserialize, Serialize};
use std::path::Path;
@@ -12,8 +13,11 @@ use typed_sled::Tree;
pub struct Database {
pub db: sled::Db,
+
pub users: Tree<String, User>,
pub invites: Tree<String, ()>,
+ pub items: Tree<String, Item>,
+ pub seek_index: Tree<(String, usize), SeekIndex>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -32,6 +36,8 @@ impl Database {
let r = Ok(Self {
users: Tree::open(&db, "users"),
invites: Tree::open(&db, "invites"),
+ items: Tree::open(&db, "items"),
+ seek_index: Tree::open(&db, "seek_index"),
db,
});
info!("ready");
diff --git a/server/src/library.rs b/server/src/library.rs
index ffd8b4a..8606a6e 100644
--- a/server/src/library.rs
+++ b/server/src/library.rs
@@ -16,33 +16,6 @@ use std::{
use crate::{routes::ui::node::AssetRole, CONF};
-pub struct Library {
- pub root: Arc<Node>,
- pub root_path: PathBuf,
-}
-
-#[derive(Debug, Clone)]
-pub enum Node {
- Directory(Arc<Directory>),
- Item(Arc<Item>),
-}
-
-#[derive(Debug, Clone)]
-pub struct Directory {
- pub lib_path: PathBuf,
- pub identifier: String,
- pub info: DirectoryInfo,
- pub children: Vec<Arc<Node>>,
-}
-
-#[derive(Debug, Clone)]
-pub struct Item {
- pub fs_path: PathBuf,
- pub lib_path: PathBuf,
- pub identifier: String,
- pub info: ItemInfo,
-}
-
impl Library {
pub fn open(path: &Path) -> anyhow::Result<Self> {
Ok(Self {
diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs
index 6f8109b..8d50c2e 100644
--- a/server/src/routes/mod.rs
+++ b/server/src/routes/mod.rs
@@ -4,7 +4,10 @@
Copyright (C) 2023 metamuffin <metamuffin.org>
*/
use crate::{database::Database, library::Library, routes::ui::error::MyResult, CONF};
-use api::{error::r_api_catch, r_api_account_login, r_api_node, r_api_assets_node, r_api_root, r_api_version};
+use api::{
+ error::r_api_catch, r_api_account_login, r_api_assets_node, r_api_node, r_api_root,
+ r_api_version,
+};
use jellyremuxer::RemuxerContext;
use rocket::{
catchers, config::SecretKey, fairing::AdHoc, fs::FileServer, get, http::Header, routes, Build,
diff --git a/server/src/routes/ui/account/settings.rs b/server/src/routes/ui/account/settings.rs
index e196b35..59b10b7 100644
--- a/server/src/routes/ui/account/settings.rs
+++ b/server/src/routes/ui/account/settings.rs
@@ -3,11 +3,6 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2023 metamuffin <metamuffin.org>
*/
-use std::ops::Range;
-use rocket::{
- form::{self, validate::len, Contextual, Form},
- get, post, FromForm, State,
-};
use super::{format_form_error, hash_password};
use crate::{
database::Database,
@@ -18,6 +13,11 @@ use crate::{
},
uri,
};
+use rocket::{
+ form::{self, validate::len, Contextual, Form},
+ get, post, FromForm, State,
+};
+use std::ops::Range;
#[derive(FromForm)]
pub struct SettingsForm {