aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--remuxer/src/matroska_to_webm.rs5
-rw-r--r--remuxer/src/seek_index.rs7
-rw-r--r--stream/src/stream_info.rs42
3 files changed, 38 insertions, 16 deletions
diff --git a/remuxer/src/matroska_to_webm.rs b/remuxer/src/matroska_to_webm.rs
index b9a1819..b77062b 100644
--- a/remuxer/src/matroska_to_webm.rs
+++ b/remuxer/src/matroska_to_webm.rs
@@ -1,3 +1,8 @@
+/*
+ This file is part of jellything (https://codeberg.org/metamuffin/jellything)
+ which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
+ Copyright (C) 2025 metamuffin <metamuffin.org>
+*/
use crate::ebml_track_entry;
use anyhow::Context;
use ebml_struct::{
diff --git a/remuxer/src/seek_index.rs b/remuxer/src/seek_index.rs
index 7296d93..82f62fb 100644
--- a/remuxer/src/seek_index.rs
+++ b/remuxer/src/seek_index.rs
@@ -53,6 +53,13 @@ pub fn get_seek_index(path: &Path) -> anyhow::Result<Arc<BTreeMap<u64, Arc<SeekI
})
}
+pub fn get_track_sizes(path: &Path) -> Result<BTreeMap<u64, usize>> {
+ Ok(get_seek_index(path)?
+ .iter()
+ .map(|(k, v)| (*k, v.blocks.iter().map(|b| b.size).sum::<usize>()))
+ .collect())
+}
+
pub fn import_seek_index(input: &mut EbmlReader) -> Result<BTreeMap<u64, SeekIndex>> {
let mut seek_index = BTreeMap::new();
while let Some(item) = input.next() {
diff --git a/stream/src/stream_info.rs b/stream/src/stream_info.rs
index c3746c6..288ea5c 100644
--- a/stream/src/stream_info.rs
+++ b/stream/src/stream_info.rs
@@ -7,8 +7,11 @@ use jellybase::{
},
CONF,
};
-use jellyremuxer::metadata::{matroska_metadata, MatroskaMetadata};
-use std::{path::PathBuf, sync::Arc};
+use jellyremuxer::{
+ metadata::{matroska_metadata, MatroskaMetadata},
+ seek_index::get_track_sizes,
+};
+use std::{collections::BTreeMap, path::PathBuf, sync::Arc};
use tokio::{
io::{AsyncWriteExt, DuplexStream},
spawn,
@@ -21,25 +24,30 @@ async fn async_matroska_metadata(path: PathBuf) -> Result<Arc<MatroskaMetadata>>
Ok(spawn_blocking(move || matroska_metadata(&path)).await??)
}
+async fn async_get_track_sizes(path: PathBuf) -> Result<BTreeMap<u64, usize>> {
+ Ok(spawn_blocking(move || get_track_sizes(&path)).await??)
+}
+
pub(crate) struct InternalStreamInfo {
pub paths: Vec<PathBuf>,
pub _metadata: Vec<Arc<MatroskaMetadata>>,
pub track_to_file: Vec<(usize, u64)>,
}
+// TODO cache mem
pub(crate) async fn stream_info(info: Arc<SMediaInfo>) -> Result<(InternalStreamInfo, StreamInfo)> {
- let mut metadata = Vec::new();
- let mut paths = Vec::new();
- for path in &info.files {
- metadata.push(async_matroska_metadata(path.clone()).await?);
- paths.push(path.clone());
- }
let mut tracks = Vec::new();
let mut track_to_file = Vec::new();
-
- for (i, m) in metadata.iter().enumerate() {
- if let Some(t) = &m.tracks {
+ 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?;
+ if let Some(t) = &metadata.tracks {
+ let duration = media_duration(&metadata);
for t in &t.entries {
+ let bitrate =
+ sizes.get(&t.track_number).copied().unwrap_or_default() as f64 / duration * 8.;
tracks.push(StreamTrackInfo {
name: None,
kind: match t.track_type {
@@ -48,21 +56,23 @@ pub(crate) async fn stream_info(info: Arc<SMediaInfo>) -> Result<(InternalStream
17 => TrackKind::Subtitle,
_ => todo!(),
},
- formats: stream_formats(t),
+ formats: stream_formats(t, bitrate),
});
track_to_file.push((i, t.track_number));
}
}
+ metadata_arr.push(metadata);
+ paths.push(path.to_owned());
}
let segment = StreamSegmentInfo {
name: None,
- duration: media_duration(&metadata[0]),
+ duration: media_duration(&metadata_arr[0]),
tracks,
};
Ok((
InternalStreamInfo {
- _metadata: metadata,
+ _metadata: metadata_arr,
paths,
track_to_file,
},
@@ -73,12 +83,12 @@ pub(crate) async fn stream_info(info: Arc<SMediaInfo>) -> Result<(InternalStream
))
}
-fn stream_formats(t: &TrackEntry) -> 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(),
remux: true,
- bitrate: 10_000_000., // TODO
+ bitrate: remux_bitrate,
containers: {
let mut x = containers_by_codec(&t.codec_id);
// TODO remove this