aboutsummaryrefslogtreecommitdiff
path: root/import/src/plugins/media_info.rs
diff options
context:
space:
mode:
Diffstat (limited to 'import/src/plugins/media_info.rs')
-rw-r--r--import/src/plugins/media_info.rs166
1 files changed, 104 insertions, 62 deletions
diff --git a/import/src/plugins/media_info.rs b/import/src/plugins/media_info.rs
index da445a3..250e417 100644
--- a/import/src/plugins/media_info.rs
+++ b/import/src/plugins/media_info.rs
@@ -5,10 +5,25 @@
*/
use crate::plugins::{ImportContext, ImportPlugin, PluginInfo};
-use anyhow::{Result, anyhow};
-use jellyremuxer::matroska::Segment;
+use anyhow::Result;
+use jellycommon::{
+ jellyobject::{Object, ObjectBuffer, Tag},
+ *,
+};
+use jellydb::table::RowNum;
+use jellyremuxer::matroska::{Segment, TrackType};
use std::path::Path;
+fn lang_str_to_tag(s: &str) -> Tag {
+ use jellycommon::*;
+ match s {
+ "eng" => LANG_ENG.0,
+ "deu" => LANG_DEU.0,
+ "jpn" => LANG_JPN.0,
+ _ => LANG_UND.0,
+ }
+}
+
pub struct MediaInfo;
impl ImportPlugin for MediaInfo {
fn info(&self) -> PluginInfo {
@@ -18,71 +33,98 @@ impl ImportPlugin for MediaInfo {
..Default::default()
}
}
- fn media(&self, ct: &ImportContext, node: NodeID, path: &Path, seg: &Segment) -> Result<()> {
- let tracks = seg
- .tracks
- .as_ref()
- .ok_or(anyhow!("no tracks"))?
- .entries
- .iter()
- .map(|track| SourceTrack {
- codec: track.codec_id.clone(),
- language: track.language.clone(),
- name: track.name.clone().unwrap_or_default(),
- federated: Vec::new(),
- kind: if let Some(video) = &track.video {
- SourceTrackKind::Video {
- width: video.pixel_width,
- height: video.pixel_height,
- fps: video.frame_rate,
- }
- } else if let Some(audio) = &track.audio {
- SourceTrackKind::Audio {
- channels: audio.channels as usize,
- sample_rate: audio.sampling_frequency,
- bit_depth: audio.bit_depth.map(|r| r as usize),
- }
- } else {
- SourceTrackKind::Subtitle
- },
- source: TrackSource::Local(path.to_owned(), track.track_number),
- })
- .collect::<Vec<_>>();
-
+ fn media(&self, ct: &ImportContext, row: RowNum, path: &Path, seg: &Segment) -> Result<()> {
let size = path.metadata()?.len();
-
- ct.db.update_node_init(node, |node| {
- node.storage_size = size;
- node.media = Some(jellycommon::MediaInfo {
- chapters: seg
- .chapters
- .clone()
- .map(|c| {
- let mut chaps = Vec::new();
- if let Some(ee) = c.edition_entries.first() {
- for ca in &ee.chapter_atoms {
- let mut labels = Vec::new();
- for cd in &ca.displays {
- for lang in &cd.languages {
- labels.push((lang.to_owned(), cd.string.clone()))
- }
- }
- chaps.push(Chapter {
- labels,
- time_start: Some(ca.time_start as f64 * 1e-9),
- time_end: ca.time_end.map(|ts| ts as f64 * 1e-9),
- })
+ ct.dba.db.write_transaction(&mut |txn| {
+ let mut node = ct.dba.nodes.get(txn, row)?.unwrap();
+ if let Some(tracks) = &seg.tracks {
+ node = node.as_object().extend_object(
+ NO_TRACK,
+ TR_SOURCE.0,
+ tracks.entries.iter().map(|t| {
+ let mut track = ObjectBuffer::empty();
+ track = track.as_object().insert(TR_CODEC, &t.codec_id);
+ track = track
+ .as_object()
+ .insert(TR_LANGUAGE, lang_str_to_tag(&t.language));
+ if let Some(name) = &t.name {
+ track = track.as_object().insert(TR_NAME, name);
+ }
+ track = track.as_object().insert(
+ TR_KIND,
+ match t.track_type {
+ TrackType::Audio => TRKIND_AUDIO,
+ TrackType::Video => TRKIND_VIDEO,
+ TrackType::Subtitle => TRKIND_TEXT,
+ _ => TRKIND_UNKNOWN,
+ },
+ );
+ if let Some(v) = &t.video {
+ track = track
+ .as_object()
+ .insert(TR_PIXEL_WIDTH, v.pixel_width as u32);
+ track = track
+ .as_object()
+ .insert(TR_PIXEL_HEIGHT, v.pixel_height as u32);
+ if let Some(fr) = v.frame_rate {
+ track = track.as_object().insert(TR_RATE, fr);
+ }
+ }
+ if let Some(a) = &t.audio {
+ track = track.as_object().insert(TR_CHANNELS, a.channels as u32);
+ track = track.as_object().insert(TR_RATE, a.sampling_frequency);
+ if let Some(d) = a.bit_depth {
+ track = track.as_object().insert(TR_BIT_DEPTH, d as u32);
}
}
- chaps
- })
- .unwrap_or_default(),
- duration: fix_invalid_runtime(
+
+ let source = Object::EMPTY
+ .insert(TRSOURCE_LOCAL_PATH, &path.to_string_lossy())
+ .as_object()
+ .insert(TRSOURCE_LOCAL_TRACKNUM, t.track_number);
+ track = track.as_object().insert(TR_SOURCE, source.as_object());
+
+ track
+ }),
+ );
+ }
+
+ if let Some(chapters) = &seg.chapters {
+ node = node.as_object().extend_object(
+ NO_CHAPTER,
+ CH_NAME.0,
+ chapters
+ .edition_entries
+ .iter()
+ .flat_map(|e| &e.chapter_atoms)
+ .map(|cha| {
+ let mut chapter = ObjectBuffer::empty();
+ chapter = chapter
+ .as_object()
+ .insert(CH_START, cha.time_start as f64 * 1e-9);
+ if let Some(end) = cha.time_end {
+ chapter = chapter.as_object().insert(CH_END, end as f64 * 1e-9);
+ }
+ if let Some(display) = cha.displays.iter().next() {
+ chapter = chapter.as_object().insert(CH_NAME, &display.string);
+ }
+ chapter
+ }),
+ );
+ }
+
+ node = node.as_object().insert(
+ NO_DURATION,
+ fix_invalid_runtime(
seg.info.duration.unwrap_or_default() * seg.info.timestamp_scale as f64 * 1e-9,
),
- tracks,
- });
- })?;
+ );
+ node = node.as_object().insert(NO_STORAGE_SIZE, size);
+
+ ct.dba.nodes.update(txn, row, node);
+
+ Ok(())
+ });
Ok(())
}