1use std::collections::HashMap;
2
3#[derive(Clone, uniffi::Record)]
4pub struct MoqDimensions {
5 pub width: u32,
6 pub height: u32,
7}
8
9#[derive(Clone, uniffi::Enum)]
10pub enum Container {
11 Legacy,
12 Cmaf { init: Vec<u8> },
13 Loc,
14}
15
16impl From<hang::catalog::Container> for Container {
17 fn from(container: hang::catalog::Container) -> Self {
18 match container {
19 hang::catalog::Container::Legacy => Self::Legacy,
20 hang::catalog::Container::Cmaf { init, .. } => Self::Cmaf { init: init.to_vec() },
21 hang::catalog::Container::Loc => Self::Loc,
22 }
23 }
24}
25
26impl From<Container> for hang::catalog::Container {
27 fn from(container: Container) -> Self {
28 match container {
29 Container::Legacy => Self::Legacy,
30 Container::Cmaf { init } => Self::Cmaf {
31 init: init.into(),
32 timescale: None,
33 track_id: None,
34 },
35 Container::Loc => Self::Loc,
36 }
37 }
38}
39
40#[derive(uniffi::Record)]
41pub struct MoqCatalog {
42 pub video: HashMap<String, MoqVideo>,
43 pub audio: HashMap<String, MoqAudio>,
44 pub display: Option<MoqDimensions>,
45 pub rotation: Option<f64>,
46 pub flip: Option<bool>,
47}
48
49#[derive(Clone, uniffi::Record)]
50pub struct MoqVideo {
51 pub codec: String,
52 pub description: Option<Vec<u8>>,
53 pub coded: Option<MoqDimensions>,
54 pub display_ratio: Option<MoqDimensions>,
55 pub bitrate: Option<u64>,
56 pub framerate: Option<f64>,
57 pub container: Container,
58}
59
60#[derive(Clone, uniffi::Record)]
61pub struct MoqAudio {
62 pub codec: String,
63 pub description: Option<Vec<u8>>,
64 pub sample_rate: u32,
65 pub channel_count: u32,
66 pub bitrate: Option<u64>,
67 pub container: Container,
68}
69
70#[derive(uniffi::Record)]
72pub struct MoqFrame {
73 pub payload: Vec<u8>,
74 pub timestamp_us: u64,
75 pub keyframe: bool,
76}
77
78pub(crate) fn convert_catalog(catalog: &moq_mux::catalog::hang::Catalog) -> MoqCatalog {
79 let video = catalog
80 .video
81 .renditions
82 .iter()
83 .map(|(name, config)| {
84 (
85 name.clone(),
86 MoqVideo {
87 codec: config.codec.to_string(),
88 description: config.description.as_ref().map(|d| d.to_vec()),
89 coded: match (config.coded_width, config.coded_height) {
90 (Some(w), Some(h)) => Some(MoqDimensions { width: w, height: h }),
91 _ => None,
92 },
93 display_ratio: match (config.display_ratio_width, config.display_ratio_height) {
94 (Some(w), Some(h)) => Some(MoqDimensions { width: w, height: h }),
95 _ => None,
96 },
97 bitrate: config.bitrate,
98 framerate: config.framerate,
99 container: config.container.clone().into(),
100 },
101 )
102 })
103 .collect();
104
105 let audio = catalog
106 .audio
107 .renditions
108 .iter()
109 .map(|(name, config)| {
110 (
111 name.clone(),
112 MoqAudio {
113 codec: config.codec.to_string(),
114 description: config.description.as_ref().map(|d| d.to_vec()),
115 sample_rate: config.sample_rate,
116 channel_count: config.channel_count,
117 bitrate: config.bitrate,
118 container: config.container.clone().into(),
119 },
120 )
121 })
122 .collect();
123
124 let display = catalog.video.display.as_ref().map(|d| MoqDimensions {
125 width: d.width,
126 height: d.height,
127 });
128
129 MoqCatalog {
130 video,
131 audio,
132 display,
133 rotation: catalog.video.rotation,
134 flip: catalog.video.flip,
135 }
136}