aboutsummaryrefslogtreecommitdiff
path: root/common/src/stream.rs
blob: aa7195e78e4f98047f6befb30c98535c9d519b50 (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
use bincode::{Decode, Encode};
/*
    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) 2024 metamuffin <metamuffin.org>
*/
#[cfg(feature = "rocket")]
use rocket::{FromForm, FromFormField, UriDisplayQuery};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "rocket", derive(FromForm, UriDisplayQuery))]
pub struct StreamSpec {
    pub tracks: Vec<usize>,
    pub format: StreamFormat,
    pub webm: Option<bool>,
    pub profile: Option<usize>,
    pub index: Option<usize>,
}

#[rustfmt::skip]
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Hash, Encode, Decode)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "rocket", derive(FromFormField, UriDisplayQuery))]
pub enum StreamFormat {
    #[cfg_attr(feature = "rocket", field(value = "original"))] Original,
    #[cfg_attr(feature = "rocket", field(value = "matroska"))] Matroska,
    #[cfg_attr(feature = "rocket", field(value = "hlsmaster"))] HlsMaster,
    #[cfg_attr(feature = "rocket", field(value = "hlsvariant"))] HlsVariant,
    #[cfg_attr(feature = "rocket", field(value = "jhlsi"))] JhlsIndex,
    #[cfg_attr(feature = "rocket", field(value = "snippet"))] Snippet,
    #[cfg_attr(feature = "rocket", field(value = "webvtt"))] Webvtt,
    #[cfg_attr(feature = "rocket", field(value = "jvtt"))] Jvtt,
}

impl Default for StreamSpec {
    fn default() -> Self {
        Self {
            tracks: Vec::new(),
            format: StreamFormat::Matroska,
            webm: Some(true),
            profile: None,
            index: None,
        }
    }
}

impl StreamSpec {
    pub fn to_query(&self) -> String {
        use std::fmt::Write;
        let mut u = String::new();
        write!(u, "format={}", self.format.ident()).unwrap();

        if !self.tracks.is_empty() {
            write!(
                u,
                "&tracks={}",
                self.tracks
                    .iter()
                    .map(|s| s.to_string())
                    .collect::<Vec<_>>()
                    .join(",")
            )
            .unwrap();
        }
        if let Some(profile) = self.profile {
            write!(u, "&profile={profile}").unwrap();
        }
        if let Some(index) = self.index {
            write!(u, "&index={index}").unwrap();
        }
        if let Some(webm) = self.webm {
            write!(u, "&webm={webm}").unwrap();
        }
        u
    }
}

impl StreamFormat {
    pub fn ident(&self) -> &'static str {
        match self {
            StreamFormat::Jvtt => "jvtt",
            StreamFormat::Original => "original",
            StreamFormat::Matroska => "matroska",
            StreamFormat::HlsMaster => "hlsmaster",
            StreamFormat::HlsVariant => "hlsvariant",
            StreamFormat::JhlsIndex => "jhlsi",
            StreamFormat::Snippet => "snippet",
            StreamFormat::Webvtt => "webvtt",
        }
    }
}