aboutsummaryrefslogtreecommitdiff
path: root/remuxer/src/lib.rs
blob: 931d5e6b9193d9ba750122f6adfc515769e470ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
    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>
*/
#![feature(random, exit_status_error)]
pub mod extract;
pub mod fragment;
pub mod metadata;
pub mod matroska_to_mpeg4;
pub mod remux;
pub mod seek_index;
pub mod segment_extractor;
pub mod trim_writer;
pub mod matroska_to_webm;

use ebml_struct::matroska::TrackEntry;
pub use fragment::write_fragment_into;
use jellymatroska::{Master, MatroskaTag};
pub use matroska_to_mpeg4::matroska_to_mpeg4;
pub use remux::remux_stream_into;

pub fn ebml_header(webm: bool) -> MatroskaTag {
    MatroskaTag::Ebml(Master::Collected(vec![
        MatroskaTag::EbmlVersion(1),
        MatroskaTag::EbmlReadVersion(1),
        MatroskaTag::EbmlMaxIdLength(4),
        MatroskaTag::EbmlMaxSizeLength(8),
        MatroskaTag::DocType(if webm {
            "webm".to_string()
        } else {
            "matroska".to_string()
        }),
        MatroskaTag::DocTypeVersion(4),
        MatroskaTag::DocTypeReadVersion(2),
    ]))
}
pub fn ebml_segment_info(title: String, duration: f64) -> MatroskaTag {
    MatroskaTag::Info(Master::Collected(vec![
        MatroskaTag::TimestampScale(1_000_000),
        MatroskaTag::Duration(duration * 1000.0),
        MatroskaTag::Title(title),
        MatroskaTag::MuxingApp("jellyremux".to_string()),
        MatroskaTag::WritingApp("jellything".to_string()),
    ]))
}

pub fn ebml_track_entry(number: u64, track: &TrackEntry) -> MatroskaTag {
    let mut els = vec![
        MatroskaTag::TrackNumber(number),
        MatroskaTag::FlagLacing(track.flag_lacing),
        MatroskaTag::Language(track.language.clone()),
        MatroskaTag::CodecID(track.codec_id.clone()),
        MatroskaTag::CodecDelay(track.codec_delay),
        MatroskaTag::SeekPreRoll(track.seek_pre_roll),
    ];
    if let Some(d) = &track.default_duration {
        els.push(MatroskaTag::DefaultDuration(*d));
    }
    match track.track_type {
        1 => {
            let video = track.video.as_ref().unwrap();
            els.push(MatroskaTag::TrackType(1));
            let mut props = vec![
                MatroskaTag::PixelWidth(video.pixel_width),
                MatroskaTag::PixelHeight(video.pixel_height),
            ];
            props.push(MatroskaTag::DisplayWidth(
                video.display_width.unwrap_or(video.pixel_width),
            ));
            props.push(MatroskaTag::DisplayHeight(
                video.display_height.unwrap_or(video.pixel_height),
            ));
            props.push(MatroskaTag::DisplayUnit(video.display_unit));
            if let Some(fps) = video.frame_rate {
                props.push(MatroskaTag::FrameRate(fps))
            }
            els.push(MatroskaTag::Video(Master::Collected(props)))
        }
        2 => {
            let audio = track.audio.as_ref().unwrap();
            els.push(MatroskaTag::TrackType(2));
            let mut props = vec![
                MatroskaTag::SamplingFrequency(audio.sampling_frequency),
                MatroskaTag::Channels(audio.channels),
            ];
            if let Some(bit_depth) = audio.bit_depth {
                props.push(MatroskaTag::BitDepth(bit_depth.try_into().unwrap()));
            }
            els.push(MatroskaTag::Audio(Master::Collected(props)));
        }
        17 => {
            els.push(MatroskaTag::TrackType(17));
        }
        _ => unreachable!(),
    }
    if let Some(d) = &track.codec_private {
        els.push(MatroskaTag::CodecPrivate(d.clone()));
    }
    MatroskaTag::TrackEntry(Master::Collected(els))
}