diff options
author | metamuffin <metamuffin@disroot.org> | 2025-09-25 04:00:51 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-09-25 04:00:51 +0200 |
commit | f8d4c438d10450ead56c0082b037e466ef5f9f24 (patch) | |
tree | 703612747f06b91f063dcd9e8a778675e6aa1303 /stream/src/stream_info.rs | |
parent | 0fe48987c336b9b50cba09355aa3c1cf11740edc (diff) | |
download | jellything-f8d4c438d10450ead56c0082b037e466ef5f9f24.tar jellything-f8d4c438d10450ead56c0082b037e466ef5f9f24.tar.bz2 jellything-f8d4c438d10450ead56c0082b037e466ef5f9f24.tar.zst |
start media processing refactor
Diffstat (limited to 'stream/src/stream_info.rs')
-rw-r--r-- | stream/src/stream_info.rs | 79 |
1 files changed, 33 insertions, 46 deletions
diff --git a/stream/src/stream_info.rs b/stream/src/stream_info.rs index 560ec9b..7ebc399 100644 --- a/stream/src/stream_info.rs +++ b/stream/src/stream_info.rs @@ -3,59 +3,51 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2025 metamuffin <metamuffin.org> */ -use crate::{SMediaInfo, CONF}; +use crate::{cues::generate_cues, metadata::read_metadata, SMediaInfo, CONF}; use anyhow::Result; -use jellyremuxer::{ - metadata::{matroska_metadata, MatroskaMetadata, MatroskaTrackEntry}, - seek_index::get_track_sizes, -}; +use jellyremuxer::matroska::{self, Segment, TrackEntry, TrackType}; use jellystream_types::{ - StreamContainer, StreamFormatInfo, StreamInfo, StreamSegmentInfo, StreamTrackInfo, TrackKind, + StreamContainer, StreamFormatInfo, StreamInfo, StreamTrackInfo, TrackKind, }; -use std::{collections::BTreeMap, path::PathBuf, sync::Arc}; -use tokio::{ - io::{AsyncWriteExt, DuplexStream}, - spawn, - task::spawn_blocking, +use std::{ + io::{Cursor, Read}, + path::PathBuf, + sync::Arc, }; -async fn async_matroska_metadata(path: PathBuf) -> Result<Arc<MatroskaMetadata>> { - spawn_blocking(move || matroska_metadata(&path)).await? -} - -async fn async_get_track_sizes(path: PathBuf) -> Result<BTreeMap<u64, usize>> { - spawn_blocking(move || get_track_sizes(&path)).await? -} - pub(crate) struct InternalStreamInfo { pub paths: Vec<PathBuf>, - pub metadata: Vec<Arc<MatroskaMetadata>>, + pub metadata: Vec<Arc<Segment>>, pub track_to_file: Vec<(usize, u64)>, } // TODO cache mem -pub(crate) async fn stream_info(info: Arc<SMediaInfo>) -> Result<(InternalStreamInfo, StreamInfo)> { +pub(crate) fn stream_info(info: Arc<SMediaInfo>) -> Result<(InternalStreamInfo, StreamInfo)> { let mut tracks = Vec::new(); let mut track_to_file = Vec::new(); let mut metadata_arr = Vec::new(); let mut paths = Vec::new(); for (i, path) in info.files.iter().enumerate() { - let metadata = async_matroska_metadata(path.clone()).await?; - let sizes = async_get_track_sizes(path.clone()).await?; + let metadata = read_metadata(&path)?; + let cue_stat = generate_cues(&path)?; if let Some(t) = &metadata.tracks { - let duration = media_duration(&metadata); + let duration = media_duration(&metadata.info); for t in &t.entries { - let bitrate = - sizes.get(&t.track_number).copied().unwrap_or_default() as f64 / duration * 8.; + let byterate = cue_stat + .stats + .get(&t.track_number) + .map(|e| e.total_size) + .unwrap_or_default() as f64 + / duration; tracks.push(StreamTrackInfo { name: None, kind: match t.track_type { - 1 => TrackKind::Video, - 2 => TrackKind::Audio, - 17 => TrackKind::Subtitle, + matroska::TrackType::Video => TrackKind::Video, + matroska::TrackType::Audio => TrackKind::Audio, + matroska::TrackType::Subtitle => TrackKind::Subtitle, _ => todo!(), }, - formats: stream_formats(t, bitrate), + formats: stream_formats(t, byterate * 8.), }); track_to_file.push((i, t.track_number)); } @@ -64,11 +56,7 @@ pub(crate) async fn stream_info(info: Arc<SMediaInfo>) -> Result<(InternalStream paths.push(path.to_owned()); } - let segment = StreamSegmentInfo { - name: None, - duration: media_duration(&metadata_arr[0]), - tracks, - }; + let duration = media_duration(&metadata_arr[0].info); // TODO different durations?! Ok(( InternalStreamInfo { metadata: metadata_arr, @@ -77,12 +65,13 @@ pub(crate) async fn stream_info(info: Arc<SMediaInfo>) -> Result<(InternalStream }, StreamInfo { name: info.title.clone(), - segments: vec![segment], + duration, + tracks, }, )) } -fn stream_formats(t: &MatroskaTrackEntry, remux_bitrate: f64) -> Vec<StreamFormatInfo> { +fn stream_formats(t: &TrackEntry, remux_bitrate: f64) -> Vec<StreamFormatInfo> { let mut formats = Vec::new(); formats.push(StreamFormatInfo { codec: t.codec_id.to_string(), @@ -97,7 +86,7 @@ fn stream_formats(t: &MatroskaTrackEntry, remux_bitrate: f64) -> Vec<StreamForma }); match t.track_type { - 1 => { + TrackType::Video => { let sw = t.video.as_ref().unwrap().pixel_width; let sh = t.video.as_ref().unwrap().pixel_height; for (w, br) in [ @@ -136,7 +125,7 @@ fn stream_formats(t: &MatroskaTrackEntry, remux_bitrate: f64) -> Vec<StreamForma } } } - 2 => { + TrackType::Audio => { for br in [256e3, 128e3, 64e3] { formats.push(StreamFormatInfo { codec: "A_OPUS".to_string(), @@ -151,7 +140,7 @@ fn stream_formats(t: &MatroskaTrackEntry, remux_bitrate: f64) -> Vec<StreamForma }); } } - 17 => {} + TrackType::Subtitle => {} _ => {} } @@ -168,13 +157,11 @@ fn containers_by_codec(codec: &str) -> Vec<StreamContainer> { } } -pub(crate) async fn write_stream_info(info: Arc<SMediaInfo>, mut b: DuplexStream) -> Result<()> { - let (_, info) = stream_info(info).await?; - spawn(async move { b.write_all(&serde_json::to_vec(&info)?).await }); - Ok(()) +pub(crate) fn write_stream_info(info: Arc<SMediaInfo>) -> Result<Box<dyn Read + Send + Sync>> { + let (_, info) = stream_info(info)?; + Ok(Box::new(Cursor::new(serde_json::to_vec(&info)?))) } -fn media_duration(m: &MatroskaMetadata) -> f64 { - let info = m.info.as_ref().unwrap(); +fn media_duration(info: &matroska::Info) -> f64 { (info.duration.unwrap_or_default() * info.timestamp_scale as f64) / 1_000_000_000. } |