aboutsummaryrefslogtreecommitdiff
path: root/stream/src/stream_info.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-09-25 04:00:51 +0200
committermetamuffin <metamuffin@disroot.org>2025-09-25 04:00:51 +0200
commitf8d4c438d10450ead56c0082b037e466ef5f9f24 (patch)
tree703612747f06b91f063dcd9e8a778675e6aa1303 /stream/src/stream_info.rs
parent0fe48987c336b9b50cba09355aa3c1cf11740edc (diff)
downloadjellything-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.rs79
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.
}